Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance create view, alter view, drop view sql parser #34283

Merged
merged 2 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
1. Encrypt: Support insert statement rewrite use quote [#34259](https://github.com/apache/shardingsphere/pull/34259)
1. SQL Binder: Support optimize table sql bind and add test case - [#34242](https://github.com/apache/shardingsphere/pull/34242)
1. SQL Binder: Support show create table, show columns, show index statement bind - [#34271](https://github.com/apache/shardingsphere/pull/34271)
1. SQL Parser: Enhance create view, alter view, drop view sql parser - [#34283](https://github.com/apache/shardingsphere/pull/34283)

### Bug Fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ private Collection<Projection> generateProjections(final EncryptColumn encryptCo
if (SubqueryType.PREDICATE == subqueryType) {
return Collections.singleton(generateProjectionInPredicateSubquery(encryptColumn, columnProjection));
}
if (SubqueryType.INSERT_SELECT == subqueryType) {
if (SubqueryType.INSERT_SELECT == subqueryType || SubqueryType.VIEW_DEFINITION == subqueryType) {
return generateProjectionsInInsertSelectSubquery(encryptColumn, columnProjection);
}
throw new UnsupportedSQLOperationException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@
package org.apache.shardingsphere.sharding.checker.sql.ddl;

import org.apache.shardingsphere.infra.binder.context.statement.ddl.AlterViewStatementContext;
import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import org.apache.shardingsphere.infra.rule.attribute.table.TableMapperRuleAttribute;
import org.apache.shardingsphere.sharding.exception.metadata.EngagedViewException;
import org.apache.shardingsphere.sharding.rule.ShardingRule;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ProjectionsSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableNameSegment;
import org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
Expand All @@ -31,8 +35,11 @@
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.Collections;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

Expand All @@ -46,10 +53,15 @@ class ShardingAlterViewSupportedCheckerTest {
void assertPreValidateAlterViewForMySQL() {
MySQLSelectStatement selectStatement = new MySQLSelectStatement();
selectStatement.setFrom(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order"))));
selectStatement.setProjections(new ProjectionsSegment(0, 0));
MySQLAlterViewStatement sqlStatement = new MySQLAlterViewStatement();
sqlStatement.setView(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order_view"))));
sqlStatement.setSelect(selectStatement);
AlterViewStatementContext sqlStatementContext = new AlterViewStatementContext(sqlStatement);
ShardingSphereMetaData metaData = mock(ShardingSphereMetaData.class);
ShardingSphereDatabase database = mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS);
when(database.getRuleMetaData().getAttributes(TableMapperRuleAttribute.class)).thenReturn(Collections.emptyList());
when(metaData.getDatabase("foo_db")).thenReturn(database);
AlterViewStatementContext sqlStatementContext = new AlterViewStatementContext(metaData, Collections.emptyList(), sqlStatement, "foo_db");
when(rule.isShardingTable("t_order")).thenReturn(false);
assertDoesNotThrow(() -> new ShardingAlterViewSupportedChecker().check(rule, mock(), mock(), sqlStatementContext));
}
Expand All @@ -58,10 +70,15 @@ void assertPreValidateAlterViewForMySQL() {
void assertPreValidateAlterViewWithShardingTableForMySQL() {
MySQLSelectStatement selectStatement = new MySQLSelectStatement();
selectStatement.setFrom(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order"))));
selectStatement.setProjections(new ProjectionsSegment(0, 0));
MySQLAlterViewStatement sqlStatement = new MySQLAlterViewStatement();
sqlStatement.setView(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order_view"))));
sqlStatement.setSelect(selectStatement);
AlterViewStatementContext sqlStatementContext = new AlterViewStatementContext(sqlStatement);
ShardingSphereMetaData metaData = mock(ShardingSphereMetaData.class);
ShardingSphereDatabase database = mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS);
when(database.getRuleMetaData().getAttributes(TableMapperRuleAttribute.class)).thenReturn(Collections.emptyList());
when(metaData.getDatabase("foo_db")).thenReturn(database);
AlterViewStatementContext sqlStatementContext = new AlterViewStatementContext(metaData, Collections.emptyList(), sqlStatement, "foo_db");
when(rule.isShardingTable("t_order")).thenReturn(true);
assertThrows(EngagedViewException.class, () -> new ShardingAlterViewSupportedChecker().check(rule, mock(), mock(), sqlStatementContext));
}
Expand All @@ -71,7 +88,7 @@ void assertPreValidateAlterRenamedView() {
OpenGaussAlterViewStatement sqlStatement = new OpenGaussAlterViewStatement();
sqlStatement.setView(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order_view"))));
sqlStatement.setRenameView(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order_new"))));
AlterViewStatementContext sqlStatementContext = new AlterViewStatementContext(sqlStatement);
AlterViewStatementContext sqlStatementContext = new AlterViewStatementContext(mock(ShardingSphereMetaData.class), Collections.emptyList(), sqlStatement, "foo_db");
assertDoesNotThrow(() -> new ShardingAlterViewSupportedChecker().check(rule, mock(), mock(), sqlStatementContext));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,10 @@ private static SQLStatementContext getDDLStatementContext(final ShardingSphereMe
return new CreateProcedureStatementContext((CreateProcedureStatement) sqlStatement);
}
if (sqlStatement instanceof CreateViewStatement) {
return new CreateViewStatementContext((CreateViewStatement) sqlStatement);
return new CreateViewStatementContext(metaData, params, (CreateViewStatement) sqlStatement, currentDatabaseName);
}
if (sqlStatement instanceof AlterViewStatement) {
return new AlterViewStatementContext((AlterViewStatement) sqlStatement);
return new AlterViewStatementContext(metaData, params, (AlterViewStatement) sqlStatement, currentDatabaseName);
}
if (sqlStatement instanceof DropViewStatement) {
return new DropViewStatementContext((DropViewStatement) sqlStatement);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,19 @@
import lombok.Getter;
import org.apache.shardingsphere.infra.binder.context.segment.table.TablesContext;
import org.apache.shardingsphere.infra.binder.context.statement.CommonSQLStatementContext;
import org.apache.shardingsphere.infra.binder.context.statement.dml.SelectStatementContext;
import org.apache.shardingsphere.infra.binder.context.type.TableAvailable;
import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
import org.apache.shardingsphere.sql.parser.statement.core.enums.SubqueryType;
import org.apache.shardingsphere.sql.parser.statement.core.extractor.TableExtractor;
import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.AlterViewStatement;
import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.SelectStatement;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;

/**
Expand All @@ -38,18 +43,39 @@ public final class AlterViewStatementContext extends CommonSQLStatementContext i

private final TablesContext tablesContext;

public AlterViewStatementContext(final AlterViewStatement sqlStatement) {
private final SelectStatementContext selectStatementContext;

public AlterViewStatementContext(final ShardingSphereMetaData metaData, final List<Object> params, final AlterViewStatement sqlStatement, final String currentDatabaseName) {
super(sqlStatement);
Collection<SimpleTableSegment> tables = new LinkedList<>();
tables.add(sqlStatement.getView());
Optional<SelectStatement> selectStatement = sqlStatement.getSelect();
selectStatement.ifPresent(optional -> {
TableExtractor extractor = new TableExtractor();
extractor.extractTablesFromSelect(optional);
tables.addAll(extractor.getRewriteTables());
});
selectStatement.ifPresent(optional -> extractTables(optional, tables));
sqlStatement.getRenameView().ifPresent(tables::add);
tablesContext = new TablesContext(tables);
selectStatementContext = selectStatement.map(optional -> createSelectStatementContext(metaData, params, optional, currentDatabaseName)).orElse(null);
}

private SelectStatementContext createSelectStatementContext(final ShardingSphereMetaData metaData, final List<Object> params, final SelectStatement selectStatement,
final String currentDatabaseName) {
SelectStatementContext result = new SelectStatementContext(metaData, params, selectStatement, currentDatabaseName, Collections.emptyList());
result.setSubqueryType(SubqueryType.VIEW_DEFINITION);
return result;
}

private void extractTables(final SelectStatement selectStatement, final Collection<SimpleTableSegment> tables) {
TableExtractor extractor = new TableExtractor();
extractor.extractTablesFromSelect(selectStatement);
tables.addAll(extractor.getRewriteTables());
}

/**
* Get select statement context.
*
* @return select statement context
*/
public Optional<SelectStatementContext> getSelectStatementContext() {
return Optional.ofNullable(selectStatementContext);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,16 @@
import lombok.Getter;
import org.apache.shardingsphere.infra.binder.context.segment.table.TablesContext;
import org.apache.shardingsphere.infra.binder.context.statement.CommonSQLStatementContext;
import org.apache.shardingsphere.infra.binder.context.statement.dml.SelectStatementContext;
import org.apache.shardingsphere.infra.binder.context.type.TableAvailable;
import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
import org.apache.shardingsphere.sql.parser.statement.core.enums.SubqueryType;
import org.apache.shardingsphere.sql.parser.statement.core.extractor.TableExtractor;
import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.CreateViewStatement;

import java.util.Collections;
import java.util.List;

/**
* Create view statement context.
*/
Expand All @@ -32,11 +38,15 @@ public final class CreateViewStatementContext extends CommonSQLStatementContext

private final TablesContext tablesContext;

public CreateViewStatementContext(final CreateViewStatement sqlStatement) {
private final SelectStatementContext selectStatementContext;

public CreateViewStatementContext(final ShardingSphereMetaData metaData, final List<Object> params, final CreateViewStatement sqlStatement, final String currentDatabaseName) {
super(sqlStatement);
TableExtractor extractor = new TableExtractor();
extractor.extractTablesFromCreateViewStatement(sqlStatement);
tablesContext = new TablesContext(extractor.getRewriteTables());
selectStatementContext = new SelectStatementContext(metaData, params, sqlStatement.getSelect(), currentDatabaseName, Collections.emptyList());
selectStatementContext.setSubqueryType(SubqueryType.VIEW_DEFINITION);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.CreateTableStatement;
import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.CreateViewStatement;
import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.DropTableStatement;
import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.DropViewStatement;
import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.RenameTableStatement;
import org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;

Expand Down Expand Up @@ -150,13 +151,18 @@ private static void checkTableExists(final SQLStatementBinderContext binderConte
return;
}
if (binderContext.getSqlStatement() instanceof CreateViewStatement && isCreateTable(((CreateViewStatement) binderContext.getSqlStatement()).getView(), tableName)) {
ShardingSpherePreconditions.checkState(binderContext.getHintValueContext().isSkipMetadataValidate() || !schema.containsTable(tableName), () -> new TableExistsException(tableName));
ShardingSpherePreconditions.checkState(binderContext.getHintValueContext().isSkipMetadataValidate()
|| ((CreateViewStatement) binderContext.getSqlStatement()).isReplaceView() || !schema.containsTable(tableName), () -> new TableExistsException(tableName));
return;
}
if (binderContext.getSqlStatement() instanceof AlterViewStatement && isRenameView((AlterViewStatement) binderContext.getSqlStatement(), tableName)) {
ShardingSpherePreconditions.checkState(binderContext.getHintValueContext().isSkipMetadataValidate() || !schema.containsTable(tableName), () -> new TableExistsException(tableName));
return;
}
if (binderContext.getSqlStatement() instanceof DropViewStatement) {
ShardingSpherePreconditions.checkState(((DropViewStatement) binderContext.getSqlStatement()).isIfExists() || schema.containsTable(tableName), () -> new TableNotFoundException(tableName));
return;
}
if ("DUAL".equalsIgnoreCase(tableName)) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public final class CreateViewStatementBinder implements SQLStatementBinder<Creat
public CreateViewStatement bind(final CreateViewStatement sqlStatement, final SQLStatementBinderContext binderContext) {
CreateViewStatement result = copy(sqlStatement);
Multimap<CaseInsensitiveString, TableSegmentBinderContext> tableBinderContexts = LinkedHashMultimap.create();
result.setReplaceView(sqlStatement.isReplaceView());
result.setView(SimpleTableSegmentBinder.bind(sqlStatement.getView(), binderContext, tableBinderContexts));
result.setSelect(new SelectStatementBinder().bind(sqlStatement.getSelect(), binderContext));
return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
package org.apache.shardingsphere.infra.binder.context.statement.ddl;

import org.apache.shardingsphere.infra.binder.context.statement.CommonSQLStatementContext;
import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import org.apache.shardingsphere.infra.rule.attribute.table.TableMapperRuleAttribute;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ProjectionsSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.bound.TableSegmentBoundInfo;
import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableNameSegment;
Expand All @@ -30,11 +34,13 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.Collections;
import java.util.Optional;

import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

Expand All @@ -53,6 +59,7 @@ void setUp() {
void assertMySQLNewInstance() {
SelectStatement select = mock(MySQLSelectStatement.class);
when(select.getFrom()).thenReturn(Optional.of(view));
when(select.getProjections()).thenReturn(new ProjectionsSegment(0, 0));
MySQLAlterViewStatement alterViewStatement = new MySQLAlterViewStatement();
alterViewStatement.setView(view);
alterViewStatement.setSelect(select);
Expand All @@ -70,7 +77,11 @@ void assertPostgreSQLNewInstance() {
}

private void assertNewInstance(final AlterViewStatement alterViewStatement) {
AlterViewStatementContext actual = new AlterViewStatementContext(alterViewStatement);
ShardingSphereMetaData metaData = mock(ShardingSphereMetaData.class);
ShardingSphereDatabase database = mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS);
when(database.getRuleMetaData().getAttributes(TableMapperRuleAttribute.class)).thenReturn(Collections.emptyList());
when(metaData.getDatabase("foo_db")).thenReturn(database);
AlterViewStatementContext actual = new AlterViewStatementContext(metaData, Collections.emptyList(), alterViewStatement, "foo_db");
assertThat(actual, instanceOf(CommonSQLStatementContext.class));
assertThat(actual.getSqlStatement(), is(alterViewStatement));
assertThat(actual.getTablesContext().getSimpleTables().size(), is(2));
Expand Down
Loading
Loading