@@ -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);
@@ -10678,27 +10693,48 @@ EqualsTo VariableExpression(): {
1067810693}
1067910694
1068010695Execute Execute(): {
10681- Token token;
1068210696 ObjectNames funcName;
10683- ExpressionList expressionList = null ;
10697+ ExpressionList expressionList;
1068410698 Execute execute = new Execute();
10685- List<Expression> namedExprList;
10686- Expression expr;
1068710699}
1068810700{
1068910701 (<K_EXEC> { execute.setExecType(Execute.ExecType.EXEC); }
1069010702 | <K_EXECUTE> { execute.setExecType(Execute.ExecType.EXECUTE); }
1069110703 | <K_CALL> { execute.setExecType(Execute.ExecType.CALL); } )
1069210704
10693- funcName=RelObjectNames() { execute.setName(funcName.getNames()); }
10705+ // A colon starts a bind argument here; it must not join the procedure name.
10706+ funcName=ColumnIdentifier() { execute.setName(funcName.getNames()); }
10707+ [ LOOKAHEAD(2) expressionList=ExecuteArguments() { execute.setExprList(expressionList); } ]
10708+ { return execute; }
10709+ }
1069410710
10711+ ExpressionList ExecuteArguments(): {
10712+ ExpressionList arguments = new ExpressionList();
10713+ Expression argument;
10714+ }
10715+ {
1069510716 (
10696- LOOKAHEAD(2) expressionList=ExpressionList() { execute.setExprList(expressionList); }
10697- )?
10717+ LOOKAHEAD("(") arguments=ExpressionList()
10718+ |
10719+ argument=ExecuteArgument() { arguments.add(argument); }
10720+ ( "," argument=ExecuteArgument() { arguments.add(argument); } )*
10721+ )
10722+ { return arguments; }
10723+ }
10724+
10725+ Expression ExecuteArgument(): {
10726+ Expression argument;
10727+ boolean output = false;
10728+ }
10729+ {
10730+ argument=Expression()
10731+ [
10732+ LOOKAHEAD({ isAccessKeywordAhead("OUTPUT") || isAccessKeywordAhead("OUT") })
10733+ ( <K_OUTPUT> | AccessKeyword("OUT") )
10734+ { output = true; }
10735+ ]
10736+ { return output ? createOutputArgument(argument) : argument; }
1069810737
10699- {
10700- return execute;
10701- }
1070210738}
1070310739
1070410740FullTextSearch FullTextSearch() : {
0 commit comments