未验证 提交 99d119d3 编写于 作者: W wenweibin 提交者: GitHub

Improve mysql Call Statement definition and Visitor #7791 (#8043)

* Improve mysql Call Statement definition and Visitor #7791

* Improve mysql Call Statement definition and Visitor #7791

* Improve mysql Call Statement definition and Visitor #7791

* Improve mysql Call Statement definition and Visitor #7791
上级 2aab6118
......@@ -17,24 +17,30 @@
package org.apache.shardingsphere.sql.parser.mysql.visitor.statement.impl;
import org.apache.shardingsphere.sql.parser.api.visitor.operation.SQLStatementVisitor;
import org.apache.shardingsphere.sql.parser.api.visitor.ASTNode;
import org.apache.shardingsphere.sql.parser.api.visitor.operation.SQLStatementVisitor;
import org.apache.shardingsphere.sql.parser.api.visitor.type.DMLSQLVisitor;
import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.CallContext;
import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.DoStatementContext;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dml.MySQLCallStatement;
import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dml.MySQLDoStatement;
import java.util.ArrayList;
import java.util.List;
/**
* DML Statement SQL visitor for MySQL.
*/
public final class MySQLDMLStatementSQLVisitor extends MySQLStatementSQLVisitor implements DMLSQLVisitor, SQLStatementVisitor {
@Override
public ASTNode visitCall(final CallContext ctx) {
return new MySQLCallStatement();
List<ExpressionSegment> parameters = new ArrayList<>();
ctx.expr().forEach(each -> parameters.add((ExpressionSegment) visit(each)));
return new MySQLCallStatement(ctx.identifier().getText(), parameters);
}
@Override
public ASTNode visitDoStatement(final DoStatementContext ctx) {
return new MySQLDoStatement();
......
......@@ -17,13 +17,26 @@
package org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dml;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.CallStatement;
import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.MySQLStatement;
import java.util.List;
/**
* MySQL call statement.
*/
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Getter
public final class MySQLCallStatement extends CallStatement implements MySQLStatement {
private String procedureName;
private List<ExpressionSegment> parameters;
}
......@@ -21,32 +21,35 @@ import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DMLStatement;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.CallStatement;
import org.apache.shardingsphere.test.sql.parser.parameterized.asserts.SQLCaseAssertContext;
import org.apache.shardingsphere.test.sql.parser.parameterized.asserts.statement.dml.impl.DeleteStatementAssert;
import org.apache.shardingsphere.test.sql.parser.parameterized.asserts.statement.dml.impl.InsertStatementAssert;
import org.apache.shardingsphere.test.sql.parser.parameterized.asserts.statement.dml.impl.SelectStatementAssert;
import org.apache.shardingsphere.test.sql.parser.parameterized.asserts.statement.dml.impl.UpdateStatementAssert;
import org.apache.shardingsphere.test.sql.parser.parameterized.asserts.statement.dml.impl.InsertStatementAssert;
import org.apache.shardingsphere.test.sql.parser.parameterized.asserts.statement.dml.impl.CallStatementAssert;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.statement.SQLParserTestCase;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.statement.dml.DeleteStatementTestCase;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.statement.dml.InsertStatementTestCase;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.statement.dml.SelectStatementTestCase;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.statement.dml.UpdateStatementTestCase;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.statement.dml.InsertStatementTestCase;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.statement.dml.CallStatementTestCase;
/**
* DML statement assert.
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class DMLStatementAssert {
/**
* Assert DML statement is correct with expected parser result.
*
* @param assertContext assert context
* @param actual actual DML statement
* @param expected expected parser result
* @param actual actual DML statement
* @param expected expected parser result
*/
public static void assertIs(final SQLCaseAssertContext assertContext, final DMLStatement actual, final SQLParserTestCase expected) {
if (actual instanceof SelectStatement) {
......@@ -57,6 +60,8 @@ public final class DMLStatementAssert {
DeleteStatementAssert.assertIs(assertContext, (DeleteStatement) actual, (DeleteStatementTestCase) expected);
} else if (actual instanceof InsertStatement) {
InsertStatementAssert.assertIs(assertContext, (InsertStatement) actual, (InsertStatementTestCase) expected);
} else if (actual instanceof CallStatement) {
CallStatementAssert.assertIs(assertContext, (CallStatement) actual, (CallStatementTestCase) expected);
}
}
}
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.shardingsphere.test.sql.parser.parameterized.asserts.statement.dml.impl;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonExpressionSegment;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.CallStatement;
import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dml.MySQLCallStatement;
import org.apache.shardingsphere.test.sql.parser.parameterized.asserts.SQLCaseAssertContext;
import org.apache.shardingsphere.test.sql.parser.parameterized.asserts.segment.expression.ExpressionAssert;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.segment.impl.call.ExpectedCallParameter;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.statement.dml.CallStatementTestCase;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
/**
* Call statement assert.
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class CallStatementAssert {
/**
* Assert call statement is correct with expected parser result.
*
* @param assertContext assert context
* @param actual actual call statement
* @param expected expected call statement test case
*/
public static void assertIs(final SQLCaseAssertContext assertContext, final CallStatement actual, final CallStatementTestCase expected) {
assertProcedureName(assertContext, actual, expected);
assertProcedureParameters(assertContext, actual, expected);
}
private static void assertProcedureParameters(final SQLCaseAssertContext assertContext, final CallStatement actual, final CallStatementTestCase expected) {
if (actual instanceof MySQLCallStatement) {
MySQLCallStatement actualStatement = (MySQLCallStatement) actual;
if (actualStatement.getParameters() != null && expected.getProcedureParameters() != null) {
assertThat(assertContext.getText("Procedure parameters assertion error: "), actualStatement.getParameters().size(), equalTo(expected.getProcedureParameters().getParameters().size()));
int count = 0;
for (ExpressionSegment each : actualStatement.getParameters()) {
assertParameter(assertContext, each, expected.getProcedureParameters().getParameters().get(count));
count++;
}
}
}
}
private static void assertParameter(final SQLCaseAssertContext assertContext, final ExpressionSegment actual, final ExpectedCallParameter expected) {
if (actual instanceof ParameterMarkerExpressionSegment) {
ExpressionAssert.assertParameterMarkerExpression(assertContext, (ParameterMarkerExpressionSegment) actual, expected.getParameterMarkerExpression());
} else if (actual instanceof LiteralExpressionSegment) {
ExpressionAssert.assertLiteralExpression(assertContext, (LiteralExpressionSegment) actual, expected.getLiteralExpression());
} else if (actual instanceof CommonExpressionSegment) {
ExpressionAssert.assertCommonExpression(assertContext, (CommonExpressionSegment) actual, expected.getCommonExpression());
}
}
private static void assertProcedureName(final SQLCaseAssertContext assertContext, final CallStatement actual, final CallStatementTestCase expected) {
if (actual instanceof MySQLCallStatement) {
assertThat(assertContext.getText("Procedure name assertion error: "), ((MySQLCallStatement) actual).getProcedureName(), equalTo(expected.getProcedureName().getName()));
}
}
}
......@@ -74,6 +74,7 @@ import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.statement.dml.InsertStatementTestCase;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.statement.dml.SelectStatementTestCase;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.statement.dml.UpdateStatementTestCase;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.statement.dml.CallStatementTestCase;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.statement.tcl.BeginTransactionStatementTestCase;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.statement.tcl.CommitStatementTestCase;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.statement.tcl.RollbackStatementTestCase;
......@@ -276,6 +277,9 @@ public final class SQLParserTestCases {
@XmlElement(name = "drop-view")
private final List<DropViewStatementTestCase> dropViewTestCase = new LinkedList<>();
@XmlElement(name = "call")
private final List<CallStatementTestCase> callProcedureTestCase = new LinkedList<>();
/**
* Get all SQL parser test cases.
......@@ -344,6 +348,7 @@ public final class SQLParserTestCases {
putAll(dropProcedureTestCase, result);
putAll(dropFunctionTestCase, result);
putAll(dropDatabaseTestCase, result);
putAll(callProcedureTestCase, result);
return result;
}
......
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.segment.impl.call;
import lombok.Getter;
import lombok.Setter;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.segment.AbstractExpectedSQLSegment;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.segment.impl.expr.complex.ExpectedCommonExpression;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.segment.impl.expr.simple.ExpectedLiteralExpression;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.segment.impl.expr.simple.ExpectedParameterMarkerExpression;
import javax.xml.bind.annotation.XmlElement;
/**
* Expected call parameter.
*/
@Getter
@Setter
public final class ExpectedCallParameter extends AbstractExpectedSQLSegment {
@XmlElement(name = "parameter-marker-expression")
private ExpectedParameterMarkerExpression parameterMarkerExpression;
@XmlElement(name = "literal-expression")
private ExpectedLiteralExpression literalExpression;
@XmlElement(name = "common-expression")
private ExpectedCommonExpression commonExpression;
}
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.segment.impl.call;
import lombok.Getter;
import lombok.Setter;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.segment.AbstractExpectedSQLSegment;
import javax.xml.bind.annotation.XmlAttribute;
/**
* Expected procedure name.
*/
@Getter
@Setter
public final class ExpectedProcedureName extends AbstractExpectedSQLSegment {
@XmlAttribute(name = "name")
private String name;
}
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.segment.impl.call;
import lombok.Getter;
import lombok.Setter;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.segment.AbstractExpectedSQLSegment;
import javax.xml.bind.annotation.XmlElement;
import java.util.LinkedList;
import java.util.List;
/**
* Expected procedure parameters.
*/
@Getter
@Setter
public final class ExpectedProcedureParameters extends AbstractExpectedSQLSegment {
@XmlElement(name = "parameter")
private List<ExpectedCallParameter> parameters = new LinkedList<>();
}
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.statement.dml;
import lombok.Getter;
import lombok.Setter;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.segment.impl.call.ExpectedProcedureName;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.segment.impl.call.ExpectedProcedureParameters;
import org.apache.shardingsphere.test.sql.parser.parameterized.jaxb.cases.domain.statement.SQLParserTestCase;
import javax.xml.bind.annotation.XmlElement;
/**
* Call statement test case.
*/
@Getter
@Setter
public final class CallStatementTestCase extends SQLParserTestCase {
@XmlElement(name = "procedure-name")
private ExpectedProcedureName procedureName;
@XmlElement(name = "parameters")
private ExpectedProcedureParameters procedureParameters;
}
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<sql-parser-test-cases>
<call sql-case-id="call_without_parameters">
<procedure-name name="p" start-index="5" stop-index="6"/>
</call>
<call sql-case-id="call_with_parameters_all_variable">
<procedure-name name="p" start-index="5" stop-index="6"/>
<parameters>
<parameter>
<common-expression literal-text="@order_id" start-index="7" stop-index="15"/>
</parameter>
<parameter>
<common-expression literal-text="@user_id" start-index="18" stop-index="25"/>
</parameter>
</parameters>
</call>
<call sql-case-id="call_with_parameters_all_placeholder">
<procedure-name name="p" start-index="5" stop-index="6"/>
<parameters>
<parameter>
<parameter-marker-expression value="0" start-index="7" stop-index="7"/>
</parameter>
<parameter>
<parameter-marker-expression value="1" start-index="10" stop-index="10"/>
</parameter>
</parameters>
</call>
<call sql-case-id="call_with_parameters_all_expression">
<procedure-name name="p" start-index="5" stop-index="6"/>
<parameters>
<parameter>
<literal-expression value="user" start-index="7" stop-index="12"/>
</parameter>
<parameter>
<literal-expression value="order" start-index="15" stop-index="21"/>
</parameter>
</parameters>
</call>
<call sql-case-id="call_with_parameters_mix">
<procedure-name name="p" start-index="5" stop-index="6"/>
<parameters>
<parameter>
<common-expression literal-text="@order_id" start-index="7" stop-index="15"/>
</parameter>
<parameter>
<literal-expression value="user" start-index="18" stop-index="23"/>
</parameter>
<parameter>
<parameter-marker-expression value="0" start-index="26" stop-index="26"/>
</parameter>
</parameters>
</call>
</sql-parser-test-cases>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<sql-cases>
<sql-case id="call_without_parameters" value="CALL p" db-types="MySQL"/>
<sql-case id="call_with_parameters_all_variable" value="CALL p(@order_id, @user_id)" db-types="MySQL" />
<sql-case id="call_with_parameters_all_placeholder" value="CALL p(?, ?) " db-types="MySQL" />
<sql-case id="call_with_parameters_all_expression" value="CALL p('user', 'order')" db-types="MySQL" />
<sql-case id="call_with_parameters_mix" value="CALL p(@order_id, 'user', ?)" db-types="MySQL" />
</sql-cases>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册