@@ -126,6 +126,21 @@ public class CCJSqlParser extends AbstractJSqlParser<CCJSqlParser> {
126126 // and must not be taken as the JSON path operator
127127 private int mapKeyDepth = 0;
128128
129+ private Expression createOutputArgument(Expression argument) throws ParseException {
130+ Expression value = argument;
131+ if (argument instanceof VariableAssignment) {
132+ value = ((VariableAssignment) argument).getExpression();
133+ } else if (argument instanceof EqualsTo
134+ && ((EqualsTo) argument).getLeftExpression() instanceof UserVariable) {
135+ value = ((EqualsTo) argument).getRightExpression();
136+ }
137+ if (!(value instanceof UserVariable || value instanceof JdbcParameter
138+ || value instanceof JdbcNamedParameter)) {
139+ throw new ParseException("An OUTPUT argument must be a variable or bind parameter");
140+ }
141+ return new net.sf.jsqlparser.statement.execute.ExecuteArgument(argument, true);
142+ }
143+
129144 private void linkAST(ASTNodeAccess access, Node node) {
130145 access.setASTNode(node);
131146 node.jjtSetValue(access);
@@ -10654,27 +10669,48 @@ EqualsTo VariableExpression(): {
1065410669}
1065510670
1065610671Execute Execute(): {
10657- Token token;
1065810672 ObjectNames funcName;
10659- ExpressionList expressionList = null ;
10673+ ExpressionList expressionList;
1066010674 Execute execute = new Execute();
10661- List<Expression> namedExprList;
10662- Expression expr;
1066310675}
1066410676{
1066510677 (<K_EXEC> { execute.setExecType(Execute.ExecType.EXEC); }
1066610678 | <K_EXECUTE> { execute.setExecType(Execute.ExecType.EXECUTE); }
1066710679 | <K_CALL> { execute.setExecType(Execute.ExecType.CALL); } )
1066810680
10669- funcName=RelObjectNames() { execute.setName(funcName.getNames()); }
10681+ // A colon starts a bind argument here; it must not join the procedure name.
10682+ funcName=ColumnIdentifier() { execute.setName(funcName.getNames()); }
10683+ [ LOOKAHEAD(2) expressionList=ExecuteArguments() { execute.setExprList(expressionList); } ]
10684+ { return execute; }
10685+ }
1067010686
10687+ ExpressionList ExecuteArguments(): {
10688+ ExpressionList arguments = new ExpressionList();
10689+ Expression argument;
10690+ }
10691+ {
1067110692 (
10672- LOOKAHEAD(2) expressionList=ExpressionList() { execute.setExprList(expressionList); }
10673- )?
10693+ LOOKAHEAD("(") arguments=ExpressionList()
10694+ |
10695+ argument=ExecuteArgument() { arguments.add(argument); }
10696+ ( "," argument=ExecuteArgument() { arguments.add(argument); } )*
10697+ )
10698+ { return arguments; }
10699+ }
10700+
10701+ Expression ExecuteArgument(): {
10702+ Expression argument;
10703+ boolean output = false;
10704+ }
10705+ {
10706+ argument=Expression()
10707+ [
10708+ LOOKAHEAD({ isAccessKeywordAhead("OUTPUT") || isAccessKeywordAhead("OUT") })
10709+ ( <K_OUTPUT> | AccessKeyword("OUT") )
10710+ { output = true; }
10711+ ]
10712+ { return output ? createOutputArgument(argument) : argument; }
1067410713
10675- {
10676- return execute;
10677- }
1067810714}
1067910715
1068010716FullTextSearch FullTextSearch() : {
0 commit comments