Skip to content

Commit

Permalink
Skip table exist validate when bind create table statement with skipM…
Browse files Browse the repository at this point in the history
…etaDadaValidate
strongduanmu committed Dec 18, 2024

Verified

This commit was signed with the committer’s verified signature.
strongduanmu Zhengqiang Duan
1 parent cc616ac commit 769b9df
Showing 19 changed files with 90 additions and 32 deletions.
Original file line number Diff line number Diff line change
@@ -61,10 +61,10 @@ private boolean isNeedBind() {

private SQLStatement bindSQLStatement(final SQLStatement statement) {
if (statement instanceof DMLStatement) {
return new DMLStatementBindEngine(metaData, currentDatabaseName).bind((DMLStatement) statement);
return new DMLStatementBindEngine(metaData, currentDatabaseName, hintValueContext).bind((DMLStatement) statement);
}
if (statement instanceof DDLStatement) {
return new DDLStatementBindEngine(metaData, currentDatabaseName).bind((DDLStatement) statement);
return new DDLStatementBindEngine(metaData, currentDatabaseName, hintValueContext).bind((DDLStatement) statement);
}
return statement;
}
Original file line number Diff line number Diff line change
@@ -51,7 +51,8 @@ public static CombineSegment bind(final CombineSegment segment, final SQLStateme
private static SubquerySegment bindSubquerySegment(final SubquerySegment segment, final SQLStatementBinderContext binderContext,
final Multimap<CaseInsensitiveMap.CaseInsensitiveString, TableSegmentBinderContext> outerTableBinderContexts) {
SubquerySegment result = new SubquerySegment(segment.getStartIndex(), segment.getStopIndex(), segment.getText());
SQLStatementBinderContext subqueryBinderContext = new SQLStatementBinderContext(binderContext.getMetaData(), binderContext.getCurrentDatabaseName(), segment.getSelect());
SQLStatementBinderContext subqueryBinderContext =
new SQLStatementBinderContext(binderContext.getMetaData(), binderContext.getCurrentDatabaseName(), binderContext.getHintValueContext(), segment.getSelect());
subqueryBinderContext.getExternalTableBinderContexts().putAll(binderContext.getExternalTableBinderContexts());
result.setSelect(new SelectStatementBinder(outerTableBinderContexts).bind(segment.getSelect(), subqueryBinderContext));
return result;
Original file line number Diff line number Diff line change
@@ -43,7 +43,8 @@ public final class SubquerySegmentBinder {
*/
public static SubquerySegment bind(final SubquerySegment segment, final SQLStatementBinderContext binderContext,
final Multimap<CaseInsensitiveString, TableSegmentBinderContext> outerTableBinderContexts) {
SQLStatementBinderContext selectBinderContext = new SQLStatementBinderContext(binderContext.getMetaData(), binderContext.getCurrentDatabaseName(), segment.getSelect());
SQLStatementBinderContext selectBinderContext =
new SQLStatementBinderContext(binderContext.getMetaData(), binderContext.getCurrentDatabaseName(), binderContext.getHintValueContext(), segment.getSelect());
selectBinderContext.getExternalTableBinderContexts().putAll(binderContext.getExternalTableBinderContexts());
SelectStatement boundSelectStatement = new SelectStatementBinder(outerTableBinderContexts).bind(segment.getSelect(), selectBinderContext);
return new SubquerySegment(segment.getStartIndex(), segment.getStopIndex(), boundSelectStatement, segment.getText());
Original file line number Diff line number Diff line change
@@ -125,8 +125,8 @@ private static IdentifierValue getSchemaName(final SimpleTableSegment segment, f

private static void checkTableExists(final SQLStatementBinderContext binderContext, final ShardingSphereSchema schema, final String schemaName, final String tableName) {
if (binderContext.getSqlStatement() instanceof CreateTableStatement) {
CreateTableStatement sqlStatement = (CreateTableStatement) binderContext.getSqlStatement();
ShardingSpherePreconditions.checkState(sqlStatement.isIfNotExists() || !schema.containsTable(tableName), () -> new TableExistsException(tableName));
ShardingSpherePreconditions.checkState(binderContext.getHintValueContext().isSkipMetadataValidate()
|| ((CreateTableStatement) binderContext.getSqlStatement()).isIfNotExists() || !schema.containsTable(tableName), () -> new TableExistsException(tableName));
return;
}
if ("DUAL".equalsIgnoreCase(tableName)) {
Original file line number Diff line number Diff line change
@@ -51,7 +51,8 @@ public static SubqueryTableSegment bind(final SubqueryTableSegment segment, fina
final Multimap<CaseInsensitiveString, TableSegmentBinderContext> tableBinderContexts,
final Multimap<CaseInsensitiveString, TableSegmentBinderContext> outerTableBinderContexts) {
fillPivotColumnNamesInBinderContext(segment, binderContext);
SQLStatementBinderContext subqueryBinderContext = new SQLStatementBinderContext(binderContext.getMetaData(), binderContext.getCurrentDatabaseName(), segment.getSubquery().getSelect());
SQLStatementBinderContext subqueryBinderContext =
new SQLStatementBinderContext(binderContext.getMetaData(), binderContext.getCurrentDatabaseName(), binderContext.getHintValueContext(), segment.getSubquery().getSelect());
subqueryBinderContext.getExternalTableBinderContexts().putAll(binderContext.getExternalTableBinderContexts());
SelectStatement boundSubSelect = new SelectStatementBinder(outerTableBinderContexts).bind(segment.getSubquery().getSelect(), subqueryBinderContext);
SubquerySegment boundSubquerySegment = new SubquerySegment(segment.getSubquery().getStartIndex(), segment.getSubquery().getStopIndex(), boundSubSelect, segment.getSubquery().getText());
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext;
import org.apache.shardingsphere.infra.hint.HintValueContext;
import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ProjectionSegment;
import org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement;
@@ -42,6 +43,8 @@ public final class SQLStatementBinderContext {

private final String currentDatabaseName;

private final HintValueContext hintValueContext;

private final SQLStatement sqlStatement;

private final Collection<String> usingColumnNames = new CaseInsensitiveSet<>();
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@
import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
import org.apache.shardingsphere.infra.binder.engine.statement.ddl.CreateTableStatementBinder;
import org.apache.shardingsphere.infra.binder.engine.statement.ddl.CursorStatementBinder;
import org.apache.shardingsphere.infra.hint.HintValueContext;
import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.CreateTableStatement;
import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.CursorStatement;
@@ -36,14 +37,16 @@ public final class DDLStatementBindEngine {

private final String currentDatabaseName;

private final HintValueContext hintValueContext;

/**
* Bind DDL statement.
*
* @param statement to be bound DDL statement
* @return bound DDL statement
*/
public DDLStatement bind(final DDLStatement statement) {
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(metaData, currentDatabaseName, statement);
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(metaData, currentDatabaseName, hintValueContext, statement);
if (statement instanceof CursorStatement) {
return new CursorStatementBinder().bind((CursorStatement) statement, binderContext);
}
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@
import org.apache.shardingsphere.infra.binder.engine.statement.dml.InsertStatementBinder;
import org.apache.shardingsphere.infra.binder.engine.statement.dml.SelectStatementBinder;
import org.apache.shardingsphere.infra.binder.engine.statement.dml.UpdateStatementBinder;
import org.apache.shardingsphere.infra.hint.HintValueContext;
import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.DMLStatement;
import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.DeleteStatement;
@@ -40,14 +41,16 @@ public final class DMLStatementBindEngine {

private final String currentDatabaseName;

private final HintValueContext hintValueContext;

/**
* Bind DML statement.
*
* @param statement to be bound DML statement
* @return bound DML statement
*/
public DMLStatement bind(final DMLStatement statement) {
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(metaData, currentDatabaseName, statement);
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(metaData, currentDatabaseName, hintValueContext, statement);
if (statement instanceof SelectStatement) {
return new SelectStatementBinder().bind((SelectStatement) statement, binderContext);
}
Original file line number Diff line number Diff line change
@@ -26,6 +26,7 @@
import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
import org.apache.shardingsphere.infra.exception.kernel.syntax.AmbiguousColumnException;
import org.apache.shardingsphere.infra.hint.HintValueContext;
import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
@@ -66,7 +67,7 @@ void assertBindWithMultiTablesJoinAndNoOwner() {
ColumnSegment columnSegment = new ColumnSegment(0, 0, new IdentifierValue("order_id"));
SelectStatement selectStatement = mock(SelectStatement.class);
when(selectStatement.getDatabaseType()).thenReturn(databaseType);
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(mock(ShardingSphereMetaData.class), "foo_db", selectStatement);
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(mock(ShardingSphereMetaData.class), "foo_db", new HintValueContext(), selectStatement);
ColumnSegment actual = ColumnSegmentBinder.bind(columnSegment, SegmentType.JOIN_ON, binderContext, tableBinderContexts, LinkedHashMultimap.create());
assertNotNull(actual.getColumnBoundInfo());
assertNull(actual.getOtherUsingColumnBoundInfo());
@@ -89,7 +90,7 @@ void assertBindFromOuterTable() {
outerTableBinderContexts.put(new CaseInsensitiveString("t_order_item"), new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundOrderItemStatusColumn))));
SelectStatement selectStatement = mock(SelectStatement.class);
when(selectStatement.getDatabaseType()).thenReturn(databaseType);
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(mock(ShardingSphereMetaData.class), "foo_db", selectStatement);
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(mock(ShardingSphereMetaData.class), "foo_db", new HintValueContext(), selectStatement);
ColumnSegment columnSegment = new ColumnSegment(0, 0, new IdentifierValue("status"));
ColumnSegment actual = ColumnSegmentBinder.bind(columnSegment, SegmentType.PROJECTION, binderContext, LinkedHashMultimap.create(), outerTableBinderContexts);
assertNotNull(actual.getColumnBoundInfo());
@@ -113,7 +114,7 @@ void assertBindWithSameTableAliasAndSameProjection() {
tableBinderContexts.put(new CaseInsensitiveString("temp"), new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundOrderItemColumn))));
SelectStatement selectStatement = mock(SelectStatement.class);
when(selectStatement.getDatabaseType()).thenReturn(databaseType);
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(mock(ShardingSphereMetaData.class), "foo_db", selectStatement);
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(mock(ShardingSphereMetaData.class), "foo_db", new HintValueContext(), selectStatement);
ColumnSegment columnSegment = new ColumnSegment(0, 0, new IdentifierValue("status"));
columnSegment.setOwner(new OwnerSegment(0, 0, new IdentifierValue("temp")));
assertThrows(AmbiguousColumnException.class, () -> ColumnSegmentBinder.bind(columnSegment, SegmentType.PROJECTION, binderContext, tableBinderContexts, LinkedHashMultimap.create()));
@@ -132,7 +133,7 @@ void assertBindWithSameTableAliasAndDifferentProjection() {
tableBinderContexts.put(new CaseInsensitiveString("temp"), new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundOrderItemColumn))));
SelectStatement selectStatement = mock(SelectStatement.class);
when(selectStatement.getDatabaseType()).thenReturn(databaseType);
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(mock(ShardingSphereMetaData.class), "foo_db", selectStatement);
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(mock(ShardingSphereMetaData.class), "foo_db", new HintValueContext(), selectStatement);
ColumnSegment columnSegment = new ColumnSegment(0, 0, new IdentifierValue("status"));
columnSegment.setOwner(new OwnerSegment(0, 0, new IdentifierValue("temp")));
ColumnSegment actual = ColumnSegmentBinder.bind(columnSegment, SegmentType.PROJECTION, binderContext, tableBinderContexts, LinkedHashMultimap.create());
@@ -159,7 +160,7 @@ void assertBindOwner() {
columnSegment.setOwner(new OwnerSegment(0, 0, new IdentifierValue("t_order")));
SelectStatement selectStatement = mock(SelectStatement.class);
when(selectStatement.getDatabaseType()).thenReturn(databaseType);
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(mock(ShardingSphereMetaData.class), "foo_db", selectStatement);
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(mock(ShardingSphereMetaData.class), "foo_db", new HintValueContext(), selectStatement);
ColumnSegment actual = ColumnSegmentBinder.bind(columnSegment, SegmentType.JOIN_ON, binderContext, tableBinderContexts, LinkedHashMultimap.create());
assertTrue(actual.getOwner().isPresent());
assertTrue(actual.getOwner().get().getTableBoundInfo().isPresent());
@@ -173,4 +174,30 @@ void assertBindOwner() {
assertThat(actual.getColumnBoundInfo().getOriginalTable().getValue(), is("t_order"));
assertThat(actual.getColumnBoundInfo().getOriginalColumn().getValue(), is("order_id"));
}

@SphereEx
@Test
void assertBindFromFunctionProjection() {
ColumnSegment boundOrderStatusColumn = new ColumnSegment(0, 0, new IdentifierValue("status"));
boundOrderStatusColumn.setColumnBoundInfo(
new ColumnSegmentBoundInfo(new TableSegmentBoundInfo(new IdentifierValue("foo_db"), new IdentifierValue("foo_db")), new IdentifierValue("t_order"), new IdentifierValue("status")));
FunctionSegment functionSegment = new FunctionSegment(0, 0, "ifnull", "ifnull(status, 0)");
functionSegment.getParameters().add(boundOrderStatusColumn);
ExpressionProjectionSegment expressionProjectionSegment = new ExpressionProjectionSegment(0, 0, "ifnull(status, 0) as status", functionSegment);
expressionProjectionSegment.setAlias(new AliasSegment(0, 0, new IdentifierValue("status")));
Multimap<CaseInsensitiveString, TableSegmentBinderContext> tableBinderContexts = LinkedHashMultimap.create();
tableBinderContexts.put(new CaseInsensitiveString("t_order"), new SimpleTableSegmentBinderContext(Collections.singleton(expressionProjectionSegment)));
SelectStatement selectStatement = mock(SelectStatement.class);
when(selectStatement.getDatabaseType()).thenReturn(databaseType);
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(mock(ShardingSphereMetaData.class), "foo_db", selectStatement);
ColumnSegment columnSegment = new ColumnSegment(0, 0, new IdentifierValue("status"));
columnSegment.setOwner(new OwnerSegment(0, 0, new IdentifierValue("t_order")));
ColumnSegment actual = ColumnSegmentBinder.bind(columnSegment, SegmentType.PROJECTION, binderContext, LinkedHashMultimap.create(), tableBinderContexts);
assertNotNull(actual.getColumnBoundInfo());
assertNull(actual.getOtherUsingColumnBoundInfo());
assertThat(actual.getColumnBoundInfo().getOriginalDatabase().getValue(), is("foo_db"));
assertThat(actual.getColumnBoundInfo().getOriginalSchema().getValue(), is("foo_db"));
assertThat(actual.getColumnBoundInfo().getOriginalTable().getValue(), is("t_order"));
assertThat(actual.getColumnBoundInfo().getOriginalColumn().getValue(), is("status"));
}
}
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@

import com.google.common.collect.LinkedHashMultimap;
import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
import org.apache.shardingsphere.infra.hint.HintValueContext;
import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExistsSubqueryExpression;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubquerySegment;
@@ -38,7 +39,7 @@ void assertBindExistsSubqueryExpression() {
MySQLSelectStatement selectStatement = new MySQLSelectStatement();
selectStatement.setProjections(new ProjectionsSegment(0, 0));
ExistsSubqueryExpression existsSubqueryExpression = new ExistsSubqueryExpression(0, 0, new SubquerySegment(0, 0, selectStatement, "t_test"));
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(mock(ShardingSphereMetaData.class), "foo_db", mock(SQLStatement.class));
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(mock(ShardingSphereMetaData.class), "foo_db", new HintValueContext(), mock(SQLStatement.class));
ExistsSubqueryExpression actual = ExistsSubqueryExpressionBinder.bind(existsSubqueryExpression, binderContext, LinkedHashMultimap.create());
assertThat(actual.getStartIndex(), is(existsSubqueryExpression.getStartIndex()));
assertThat(actual.getStopIndex(), is(existsSubqueryExpression.getStopIndex()));
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@
import com.google.common.collect.LinkedHashMultimap;
import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType;
import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
import org.apache.shardingsphere.infra.hint.HintValueContext;
import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.FunctionSegment;
import org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement;
@@ -34,7 +35,7 @@ class FunctionExpressionSegmentBinderTest {
@Test
void assertBindFunctionExpressionSegment() {
FunctionSegment functionSegment = new FunctionSegment(0, 0, "CONCAT", "('%','abc','%')");
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(new ShardingSphereMetaData(), "foo_db", mock(SQLStatement.class));
SQLStatementBinderContext binderContext = new SQLStatementBinderContext(new ShardingSphereMetaData(), "foo_db", new HintValueContext(), mock(SQLStatement.class));
FunctionSegment actual = FunctionExpressionSegmentBinder.bind(functionSegment, SegmentType.PROJECTION, binderContext, LinkedHashMultimap.create(), LinkedHashMultimap.create());
assertThat(actual.getStartIndex(), is(functionSegment.getStartIndex()));
assertThat(actual.getStopIndex(), is(functionSegment.getStopIndex()));
Loading

0 comments on commit 769b9df

Please sign in to comment.