From d30870aa2472fe816ea6d14fea8091b7e36709e2 Mon Sep 17 00:00:00 2001 From: LotusMoon Date: Sun, 7 Jan 2024 19:39:00 +0800 Subject: [PATCH] Support for SQLServer parse update statistics sql (#29655) * add update statistics Segment * Add support for update statistics * Add test rules for update statistics * replace import collection * add java doc in segment * Adjust spotless appley * Adjust spotless appley --- .../main/antlr4/imports/sqlserver/BaseRule.g4 | 2 +- .../antlr4/imports/sqlserver/DDLStatement.g4 | 25 +++ .../main/antlr4/imports/sqlserver/Keyword.g4 | 8 + .../imports/sqlserver/SQLServerKeyword.g4 | 28 +++ .../sql/parser/autogen/SQLServerStatement.g4 | 1 + .../statement/SQLServerStatementVisitor.java | 107 +++++++++++ .../core/database/visitor/SQLVisitorRule.java | 4 +- .../SQLServerUpdateStatisticsStatement.java | 45 +++++ .../segment/SampleOptionSegment.java | 53 +++++ .../sqlserver/segment/SampleStrategy.java | 30 +++ .../statement/sqlserver/segment/ScanUnit.java | 28 +++ .../segment/StatisticsDimension.java | 30 +++ .../segment/StatisticsOptionSegment.java | 51 +++++ .../segment/StatisticsStrategySegment.java | 45 +++++ .../statistics/SampleOptionAssert.java | 90 +++++++++ .../statistics/StatisticsOptionAssert.java | 68 +++++++ .../statistics/StatisticsStrategyAssert.java | 66 +++++++ .../statement/ddl/DDLStatementAssert.java | 5 + ...ServerUpdateStatisticsStatementAssert.java | 83 ++++++++ .../parser/jaxb/RootSQLParserTestCases.java | 4 + .../impl/statistics/ExpectedSampleOption.java | 46 +++++ .../statistics/ExpectedStatisticsOption.java | 44 +++++ .../ExpectedStatisticsStrategy.java | 35 ++++ .../UpdateStatisticsStatementTestCase.java | 42 ++++ .../resources/case/ddl/update-statistics.xml | 72 +++++++ .../main/resources/case/dml/select-join.xml | 181 ++++++++++++++++++ .../sql/supported/ddl/update-statistics.xml | 26 +++ .../sql/supported/dml/select-join.xml | 3 + 28 files changed, 1220 insertions(+), 2 deletions(-) create mode 100644 parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/ddl/SQLServerUpdateStatisticsStatement.java create mode 100644 parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/SampleOptionSegment.java create mode 100644 parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/SampleStrategy.java create mode 100644 parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/ScanUnit.java create mode 100644 parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/StatisticsDimension.java create mode 100644 parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/StatisticsOptionSegment.java create mode 100644 parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/StatisticsStrategySegment.java create mode 100644 test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/statistics/SampleOptionAssert.java create mode 100644 test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/statistics/StatisticsOptionAssert.java create mode 100644 test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/statistics/StatisticsStrategyAssert.java create mode 100644 test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/ddl/impl/sqlserver/SQLServerUpdateStatisticsStatementAssert.java create mode 100644 test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/statistics/ExpectedSampleOption.java create mode 100644 test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/statistics/ExpectedStatisticsOption.java create mode 100644 test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/statistics/ExpectedStatisticsStrategy.java create mode 100644 test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/UpdateStatisticsStatementTestCase.java create mode 100644 test/it/parser/src/main/resources/case/ddl/update-statistics.xml create mode 100644 test/it/parser/src/main/resources/sql/supported/ddl/update-statistics.xml diff --git a/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/BaseRule.g4 b/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/BaseRule.g4 index 1934827c85b83..266be49cf2259 100644 --- a/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/BaseRule.g4 +++ b/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/BaseRule.g4 @@ -120,7 +120,7 @@ unreservedWord | DATA_RETENTION | TEMPORAL_HISTORY_RETENTION | EDITION | MIXED_PAGE_ALLOCATION | DISABLED | ALLOWED | HADR | MULTI_USER | RESTRICTED_USER | SINGLE_USER | OFFLINE | EMERGENCY | SUSPEND | DATE_CORRELATION_OPTIMIZATION | ELASTIC_POOL | SERVICE_OBJECTIVE | DATABASE_NAME | ALLOW_CONNECTIONS | GEO | NAMED | DATEFIRST | BACKUP_STORAGE_REDUNDANCY | FORCE_FAILOVER_ALLOW_DATA_LOSS | SECONDARY | FAILOVER | DEFAULT_FULLTEXT_LANGUAGE | DEFAULT_LANGUAGE | INLINE | NESTED_TRIGGERS | TRANSFORM_NOISE_WORDS | TWO_DIGIT_YEAR_CUTOFF | PERSISTENT_LOG_BUFFER | DIRECTORY_NAME | DATEFORMAT | DELAYED_DURABILITY | TRANSFER | SCHEMA | PASSWORD | AUTHORIZATION - | MEMBER | SEARCH | TEXT | SECOND | PRECISION | VIEWS | PROVIDER + | MEMBER | SEARCH | TEXT | SECOND | PRECISION | VIEWS | PROVIDER | COLUMNS ; databaseName diff --git a/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/DDLStatement.g4 b/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/DDLStatement.g4 index 75df70ed36293..9d02be374f282 100644 --- a/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/DDLStatement.g4 +++ b/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/DDLStatement.g4 @@ -147,6 +147,31 @@ truncateTable : TRUNCATE TABLE tableName ; +updateStatistics + : UPDATE STATISTICS tableName (LP_? indexName (COMMA_ indexName)* RP_?)? statisticsWithClause? + ; + +statisticsWithClause + : WITH sampleOption? statisticsOptions? + ; + +sampleOption + : (FULLSCAN | (SAMPLE NUMBER_ (PERCENT | ROWS))) (PERSIST_SAMPLE_PERCENT EQ_ (ON | OFF))? + | RESAMPLE (ON PARTITIONS LP_ NUMBER_ (COMMA_ NUMBER_)* RP_)? + ; + +statisticsOptions + : (COMMA_? statisticsOption)+ + ; + +statisticsOption + : ALL | COLUMNS | INDEX + | NORECOMPUTE + | INCREMENTAL EQ_ (ON | OFF) + | MAXDOP EQ_ NUMBER_ + | AUTO_DROP EQ_ (ON | OFF) + ; + fileTableClause : (AS FILETABLE)? ; diff --git a/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/Keyword.g4 b/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/Keyword.g4 index 1eb79442040ba..16f5914fcef4a 100644 --- a/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/Keyword.g4 +++ b/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/Keyword.g4 @@ -83,6 +83,10 @@ COLUMN : C O L U M N ; +COLUMNS + : C O L U M N S + ; + INDEX : I N D E X ; @@ -227,6 +231,10 @@ ON : O N ; +OFF + : O F F + ; + IF : I F ; diff --git a/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/SQLServerKeyword.g4 b/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/SQLServerKeyword.g4 index 9aabc67b9b70d..bfd6996455275 100644 --- a/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/SQLServerKeyword.g4 +++ b/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/SQLServerKeyword.g4 @@ -1914,3 +1914,31 @@ XMLNAMESPACES APPLY : A P P L Y ; + +STATISTICS + : S T A T I S T I C S + ; + +FULLSCAN + : F U L L S C A N + ; + +SAMPLE + : S A M P L E + ; + +RESAMPLE + : R E S A M P L E + ; + +NORECOMPUTE + : N O R E C O M P U T E + ; + +AUTO_DROP + : A U T O UL_ D R O P + ; + +PERSIST_SAMPLE_PERCENT + : P E R S I S T UL_ S A M P L E UL_ P E R C E N T + ; diff --git a/parser/sql/dialect/sqlserver/src/main/antlr4/org/apache/shardingsphere/sql/parser/autogen/SQLServerStatement.g4 b/parser/sql/dialect/sqlserver/src/main/antlr4/org/apache/shardingsphere/sql/parser/autogen/SQLServerStatement.g4 index 2147c65ff161a..506976ae205bf 100644 --- a/parser/sql/dialect/sqlserver/src/main/antlr4/org/apache/shardingsphere/sql/parser/autogen/SQLServerStatement.g4 +++ b/parser/sql/dialect/sqlserver/src/main/antlr4/org/apache/shardingsphere/sql/parser/autogen/SQLServerStatement.g4 @@ -78,5 +78,6 @@ execute | explain | setUser | revert + | updateStatistics ) SEMI_? ; diff --git a/parser/sql/dialect/sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/sqlserver/visitor/statement/SQLServerStatementVisitor.java b/parser/sql/dialect/sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/sqlserver/visitor/statement/SQLServerStatementVisitor.java index a4b06d510f338..757b1f7d7f9df 100644 --- a/parser/sql/dialect/sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/sqlserver/visitor/statement/SQLServerStatementVisitor.java +++ b/parser/sql/dialect/sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/sqlserver/visitor/statement/SQLServerStatementVisitor.java @@ -107,6 +107,11 @@ import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.ViewNameContext; import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.WhereClauseContext; import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.WithClauseContext; +import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.UpdateStatisticsContext; +import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.StatisticsWithClauseContext; +import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.StatisticsOptionContext; +import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.StatisticsOptionsContext; +import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.SampleOptionContext; import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.InsertExecClauseContext; import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.ExecContext; import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.ProcedureNameContext; @@ -187,10 +192,17 @@ import org.apache.shardingsphere.sql.parser.sql.common.value.parametermarker.ParameterMarkerValue; import org.apache.shardingsphere.sql.parser.sql.dialect.segment.sqlserver.exec.ExecSegment; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.ddl.SQLServerCreateTableStatement; +import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.ddl.SQLServerUpdateStatisticsStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.dml.SQLServerDeleteStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.dml.SQLServerInsertStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.dml.SQLServerSelectStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.dml.SQLServerUpdateStatement; +import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.segment.SampleOptionSegment; +import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.segment.SampleStrategy; +import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.segment.ScanUnit; +import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.segment.StatisticsDimension; +import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.segment.StatisticsOptionSegment; +import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.segment.StatisticsStrategySegment; import java.util.Collection; import java.util.Collections; @@ -1378,4 +1390,99 @@ public ASTNode visitCreateTableAsSelectClause(final CreateTableAsSelectClauseCon } return result; } + + @Override + public ASTNode visitUpdateStatistics(final UpdateStatisticsContext ctx) { + SQLServerUpdateStatisticsStatement result = new SQLServerUpdateStatisticsStatement(); + if (null != ctx.tableName()) { + result.setTable((SimpleTableSegment) visit(ctx.tableName())); + } + if (null != ctx.indexName() && ctx.indexName().size() > 0) { + List indexSegments = new LinkedList<>(); + for (IndexNameContext indexNameContext : ctx.indexName()) { + indexSegments.add((IndexSegment) visit(indexNameContext)); + } + result.setIndexes(indexSegments); + } + if (null != ctx.statisticsWithClause()) { + result.setStrategy((StatisticsStrategySegment) visit(ctx.statisticsWithClause())); + } + return result; + } + + @Override + public ASTNode visitStatisticsWithClause(final StatisticsWithClauseContext ctx) { + StatisticsStrategySegment result = new StatisticsStrategySegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex()); + if (null != ctx.sampleOption()) { + result.setSampleOption((SampleOptionSegment) visit(ctx.sampleOption())); + } + if (null != ctx.statisticsOptions()) { + result.setStatisticsOptions((StatisticsOptionSegment) visit(ctx.statisticsOptions())); + } + return result; + } + + @Override + public ASTNode visitStatisticsOption(final StatisticsOptionContext ctx) { + return super.visitStatisticsOption(ctx); + } + + @Override + public ASTNode visitSampleOption(final SampleOptionContext ctx) { + SampleOptionSegment result = new SampleOptionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex()); + if (null != ctx.FULLSCAN()) { + result.setStrategy(SampleStrategy.FULLSCAN); + } else if (null != ctx.SAMPLE()) { + result.setStrategy(SampleStrategy.SAMPLE); + if (null != ctx.NUMBER_()) { + List number = ctx.NUMBER_(); + result.setSampleNumber(number.get(0).getText()); + } + if (null != ctx.PERCENT()) { + result.setScanUnit(ScanUnit.PERCENT); + } else if (null != ctx.ROWS()) { + result.setScanUnit(ScanUnit.ROWS); + } + } else if (null != ctx.RESAMPLE()) { + result.setStrategy(SampleStrategy.RESAMPLE); + if (null != ctx.NUMBER_()) { + List partitions = new LinkedList<>(); + for (TerminalNode terminalNode : ctx.NUMBER_()) { + partitions.add(terminalNode.getText()); + } + result.setPartitions(partitions); + } + } + if (null != ctx.PERSIST_SAMPLE_PERCENT()) { + result.setPersistSamplePercent(null != ctx.ON()); + } + return result; + } + + @Override + public ASTNode visitStatisticsOptions(final StatisticsOptionsContext ctx) { + StatisticsOptionSegment result = new StatisticsOptionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex()); + for (StatisticsOptionContext option : ctx.statisticsOption()) { + if (null != option.ALL()) { + result.setStatisticsDimension(StatisticsDimension.ALL); + } else if (null != option.COLUMNS()) { + result.setStatisticsDimension(StatisticsDimension.COLUMNS); + } else if (null != option.INDEX()) { + result.setStatisticsDimension(StatisticsDimension.INDEX); + } + if (null != option.NORECOMPUTE()) { + result.setNoRecompute(true); + } + if (null != option.INCREMENTAL()) { + result.setIncremental(null != option.ON()); + } + if (null != option.MAXDOP()) { + result.setMaxDegreeOfParallelism(option.NUMBER_().getText()); + } + if (null != option.AUTO_DROP()) { + result.setAutoDrop(null != option.ON()); + } + } + return result; + } } diff --git a/parser/sql/engine/src/main/java/org/apache/shardingsphere/sql/parser/core/database/visitor/SQLVisitorRule.java b/parser/sql/engine/src/main/java/org/apache/shardingsphere/sql/parser/core/database/visitor/SQLVisitorRule.java index 66345c7e728f1..aa8e0345d45bd 100644 --- a/parser/sql/engine/src/main/java/org/apache/shardingsphere/sql/parser/core/database/visitor/SQLVisitorRule.java +++ b/parser/sql/engine/src/main/java/org/apache/shardingsphere/sql/parser/core/database/visitor/SQLVisitorRule.java @@ -703,7 +703,9 @@ public enum SQLVisitorRule { SWITCH("Switch", SQLStatementType.DDL), - CREATE_PROFILE("CreateProfile", SQLStatementType.DDL); + CREATE_PROFILE("CreateProfile", SQLStatementType.DDL), + + UPDATE_STATISTICS("UpdateStatistics", SQLStatementType.DDL); private final String name; diff --git a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/ddl/SQLServerUpdateStatisticsStatement.java b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/ddl/SQLServerUpdateStatisticsStatement.java new file mode 100644 index 0000000000000..9f3e6c45f2bf9 --- /dev/null +++ b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/ddl/SQLServerUpdateStatisticsStatement.java @@ -0,0 +1,45 @@ +/* + * 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.sql.parser.sql.dialect.statement.sqlserver.ddl; + +import lombok.Getter; +import lombok.Setter; +import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexSegment; +import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment; +import org.apache.shardingsphere.sql.parser.sql.common.statement.AbstractSQLStatement; +import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DDLStatement; +import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.SQLServerStatement; +import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.segment.StatisticsStrategySegment; + +import java.util.List; + +/** + * SQLServer update statistics statement. + */ +@Getter +public final class SQLServerUpdateStatisticsStatement extends AbstractSQLStatement implements DDLStatement, SQLServerStatement { + + @Setter + private List indexes; + + @Setter + private SimpleTableSegment table; + + @Setter + private StatisticsStrategySegment strategy; +} diff --git a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/SampleOptionSegment.java b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/SampleOptionSegment.java new file mode 100644 index 0000000000000..9f88a2cf0a7c1 --- /dev/null +++ b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/SampleOptionSegment.java @@ -0,0 +1,53 @@ +/* + * 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.sql.parser.sql.dialect.statement.sqlserver.segment; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment; + +import java.util.List; + +/** + * Update statistics sample option segment. + */ +@Getter +@Setter +@NoArgsConstructor +public final class SampleOptionSegment implements SQLSegment { + + private int startIndex; + + private int stopIndex; + + private boolean persistSamplePercent; + + private String sampleNumber; + + private SampleStrategy strategy; + + private ScanUnit scanUnit; + + private List partitions; + + public SampleOptionSegment(final int startIndex, final int stopIndex) { + this.startIndex = startIndex; + this.stopIndex = stopIndex; + } +} diff --git a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/SampleStrategy.java b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/SampleStrategy.java new file mode 100644 index 0000000000000..8aad5355f3952 --- /dev/null +++ b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/SampleStrategy.java @@ -0,0 +1,30 @@ +/* + * 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.sql.parser.sql.dialect.statement.sqlserver.segment; + +/** + * Update statistics sample strategy enum. + */ +public enum SampleStrategy { + + FULLSCAN, + + SAMPLE, + + RESAMPLE +} diff --git a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/ScanUnit.java b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/ScanUnit.java new file mode 100644 index 0000000000000..d1f74294ed144 --- /dev/null +++ b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/ScanUnit.java @@ -0,0 +1,28 @@ +/* + * 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.sql.parser.sql.dialect.statement.sqlserver.segment; + +/** + * Update statistics scan unit enum. + */ +public enum ScanUnit { + + ROWS, + + PERCENT +} diff --git a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/StatisticsDimension.java b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/StatisticsDimension.java new file mode 100644 index 0000000000000..b34bc5cc07907 --- /dev/null +++ b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/StatisticsDimension.java @@ -0,0 +1,30 @@ +/* + * 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.sql.parser.sql.dialect.statement.sqlserver.segment; + +/** + * Update statistics dimension enum. + */ +public enum StatisticsDimension { + + ALL, + + COLUMNS, + + INDEX +} diff --git a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/StatisticsOptionSegment.java b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/StatisticsOptionSegment.java new file mode 100644 index 0000000000000..c5e8b07b8c678 --- /dev/null +++ b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/StatisticsOptionSegment.java @@ -0,0 +1,51 @@ +/* + * 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.sql.parser.sql.dialect.statement.sqlserver.segment; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment; + +/** + * Update statistics option segment. + */ +@Getter +@Setter +@NoArgsConstructor +public final class StatisticsOptionSegment implements SQLSegment { + + private int startIndex; + + private int stopIndex; + + private StatisticsDimension statisticsDimension; + + private String maxDegreeOfParallelism; + + private boolean noRecompute; + + private boolean incremental; + + private boolean autoDrop; + + public StatisticsOptionSegment(final int startIndex, final int stopIndex) { + this.startIndex = startIndex; + this.stopIndex = stopIndex; + } +} diff --git a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/StatisticsStrategySegment.java b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/StatisticsStrategySegment.java new file mode 100644 index 0000000000000..93d3165445615 --- /dev/null +++ b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/sqlserver/segment/StatisticsStrategySegment.java @@ -0,0 +1,45 @@ +/* + * 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.sql.parser.sql.dialect.statement.sqlserver.segment; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment; + +/** + * Update statistics strategy segment. + */ +@Getter +@Setter +@NoArgsConstructor +public final class StatisticsStrategySegment implements SQLSegment { + + private int startIndex; + + private int stopIndex; + + private SampleOptionSegment sampleOption; + + private StatisticsOptionSegment statisticsOptions; + + public StatisticsStrategySegment(final int startIndex, final int stopIndex) { + this.startIndex = startIndex; + this.stopIndex = stopIndex; + } +} diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/statistics/SampleOptionAssert.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/statistics/SampleOptionAssert.java new file mode 100644 index 0000000000000..089ff32d4b393 --- /dev/null +++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/statistics/SampleOptionAssert.java @@ -0,0 +1,90 @@ +/* + * 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.it.sql.parser.internal.asserts.segment.statistics; + +import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.segment.SampleOptionSegment; +import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.SQLCaseAssertContext; +import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.SQLSegmentAssert; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.statistics.ExpectedSampleOption; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +/** + * Sample option assert. + */ +public final class SampleOptionAssert { + + /** + * Assert actual sample option segment is correct with expected returning clause. + * + * @param assertContext assert context + * @param actual actual sample option segment + * @param expected expected sample option clause + */ + public static void assertIs(final SQLCaseAssertContext assertContext, final SampleOptionSegment actual, final ExpectedSampleOption expected) { + assertStrategy(assertContext, actual, expected); + assertSampleNumber(assertContext, actual, expected); + assertScanUnit(assertContext, actual, expected); + assertPartitions(assertContext, actual, expected); + assertThat(assertContext.getText("persistSamplePercent assertion error: "), actual.isPersistSamplePercent(), is(expected.isPersistSamplePercent())); + SQLSegmentAssert.assertIs(assertContext, actual, expected); + } + + private static void assertStrategy(final SQLCaseAssertContext assertContext, final SampleOptionSegment actual, final ExpectedSampleOption expected) { + if (null == expected.getStrategy()) { + assertNull(actual.getStrategy(), assertContext.getText("Actual strategy should not exist.")); + } else { + assertNotNull(actual.getStrategy(), assertContext.getText("Actual strategy should exist.")); + assertThat(assertContext.getText("strategy assertion error: "), actual.getStrategy().name(), is(expected.getStrategy())); + } + } + + private static void assertSampleNumber(final SQLCaseAssertContext assertContext, final SampleOptionSegment actual, final ExpectedSampleOption expected) { + if (null == expected.getSampleNumber()) { + assertNull(actual.getSampleNumber(), assertContext.getText("Actual sample number should not exist.")); + } else { + assertNotNull(actual.getSampleNumber(), assertContext.getText("Actual sample number should exist.")); + assertThat(assertContext.getText("sample number assertion error: "), actual.getSampleNumber(), is(expected.getSampleNumber())); + } + } + + private static void assertScanUnit(final SQLCaseAssertContext assertContext, final SampleOptionSegment actual, final ExpectedSampleOption expected) { + if (null == expected.getScanUnit()) { + assertNull(actual.getScanUnit(), assertContext.getText("Actual scan unit should not exist.")); + } else { + assertNotNull(actual.getScanUnit(), assertContext.getText("Actual scan unit should exist.")); + assertThat(assertContext.getText("scan unit assertion error: "), actual.getScanUnit().name(), is(expected.getScanUnit())); + } + } + + private static void assertPartitions(final SQLCaseAssertContext assertContext, final SampleOptionSegment actual, final ExpectedSampleOption expected) { + if (null == expected.getPartitions()) { + assertNull(actual.getPartitions(), assertContext.getText("Actual partitions should not exist.")); + } else { + assertNotNull(actual.getPartitions(), assertContext.getText("Actual partitions should exist.")); + int count = 0; + for (String partition : expected.getPartitions()) { + assertThat(assertContext.getText("partition assertion error: "), actual.getPartitions().get(count), is(partition)); + count++; + } + } + } +} diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/statistics/StatisticsOptionAssert.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/statistics/StatisticsOptionAssert.java new file mode 100644 index 0000000000000..c8a3f098ceb4f --- /dev/null +++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/statistics/StatisticsOptionAssert.java @@ -0,0 +1,68 @@ +/* + * 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.it.sql.parser.internal.asserts.segment.statistics; + +import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.segment.StatisticsOptionSegment; +import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.SQLCaseAssertContext; +import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.SQLSegmentAssert; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.statistics.ExpectedStatisticsOption; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +/** + * Statistics option assert. + */ +public final class StatisticsOptionAssert { + + /** + * Assert actual statistics option segment is correct with expected returning clause. + * + * @param assertContext assert context + * @param actual actual sample option segment + * @param expected expected sample option clause + */ + public static void assertIs(final SQLCaseAssertContext assertContext, final StatisticsOptionSegment actual, final ExpectedStatisticsOption expected) { + assertDimension(assertContext, actual, expected); + assertMaxDegreeOfParallelism(assertContext, actual, expected); + assertThat(assertContext.getText("noRecompute assertion error: "), actual.isNoRecompute(), is(expected.isNoRecompute())); + assertThat(assertContext.getText("incremental assertion error: "), actual.isIncremental(), is(expected.isIncremental())); + assertThat(assertContext.getText("autoDrop assertion error: "), actual.isAutoDrop(), is(expected.isAutoDrop())); + SQLSegmentAssert.assertIs(assertContext, actual, expected); + } + + private static void assertDimension(final SQLCaseAssertContext assertContext, final StatisticsOptionSegment actual, final ExpectedStatisticsOption expected) { + if (null == expected.getStatisticsDimension()) { + assertNull(actual.getStatisticsDimension(), assertContext.getText("Actual dimension should not exist.")); + } else { + assertNotNull(actual.getStatisticsDimension(), assertContext.getText("Actual dimension strategy should exist.")); + assertThat(assertContext.getText("dimension assertion error: "), actual.getStatisticsDimension().name(), is(expected.getStatisticsDimension())); + } + } + + private static void assertMaxDegreeOfParallelism(final SQLCaseAssertContext assertContext, final StatisticsOptionSegment actual, final ExpectedStatisticsOption expected) { + if (null == expected.getMaxDegreeOfParallelism()) { + assertNull(actual.getMaxDegreeOfParallelism(), assertContext.getText("Actual max degree parallelism should not exist.")); + } else { + assertNotNull(actual.getMaxDegreeOfParallelism(), assertContext.getText("Actual max degree parallelism strategy should exist.")); + assertThat(assertContext.getText("max degree parallelism assertion error: "), actual.getMaxDegreeOfParallelism(), is(expected.getMaxDegreeOfParallelism())); + } + } +} diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/statistics/StatisticsStrategyAssert.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/statistics/StatisticsStrategyAssert.java new file mode 100644 index 0000000000000..47eb8b39e08e4 --- /dev/null +++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/statistics/StatisticsStrategyAssert.java @@ -0,0 +1,66 @@ +/* + * 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.it.sql.parser.internal.asserts.segment.statistics; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.segment.StatisticsStrategySegment; +import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.SQLCaseAssertContext; +import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.SQLSegmentAssert; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.statistics.ExpectedStatisticsStrategy; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +/** + * Statistics strategy assert. + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class StatisticsStrategyAssert { + + /** + * Assert actual statistics strategy segment is correct with expected returning clause. + * + * @param assertContext assert context + * @param actual actual statistics strategy segment + * @param expected expected statistics strategy clause + */ + public static void assertIs(final SQLCaseAssertContext assertContext, final StatisticsStrategySegment actual, final ExpectedStatisticsStrategy expected) { + assertSampleOption(assertContext, actual, expected); + assertStatisticsOption(assertContext, actual, expected); + SQLSegmentAssert.assertIs(assertContext, actual, expected); + } + + private static void assertSampleOption(final SQLCaseAssertContext assertContext, final StatisticsStrategySegment actual, final ExpectedStatisticsStrategy expected) { + if (null == expected.getSampleOption()) { + assertNull(actual.getSampleOption(), assertContext.getText("Actual sample option segment should not exist.")); + } else { + assertNotNull(actual.getSampleOption(), assertContext.getText("Actual sample option segment should exist.")); + SampleOptionAssert.assertIs(assertContext, actual.getSampleOption(), expected.getSampleOption()); + } + } + + private static void assertStatisticsOption(final SQLCaseAssertContext assertContext, final StatisticsStrategySegment actual, final ExpectedStatisticsStrategy expected) { + if (null == expected.getStatisticsOption()) { + assertNull(actual.getStatisticsOptions(), assertContext.getText("Actual statistics option segment should not exist.")); + } else { + assertNotNull(actual.getStatisticsOptions(), assertContext.getText("Actual statistics option segment should exist.")); + StatisticsOptionAssert.assertIs(assertContext, actual.getStatisticsOptions(), expected.getStatisticsOption()); + } + } +} diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/ddl/DDLStatementAssert.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/ddl/DDLStatementAssert.java index 67c52260951b0..b96179642dc31 100644 --- a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/ddl/DDLStatementAssert.java +++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/ddl/DDLStatementAssert.java @@ -54,6 +54,7 @@ import org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleAuditStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleDisassociateStatisticsStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleNoAuditStatement; +import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.ddl.SQLServerUpdateStatisticsStatement; import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.SQLCaseAssertContext; import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.ddl.impl.AlterIndexStatementAssert; import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.ddl.impl.AlterSessionStatementAssert; @@ -89,6 +90,7 @@ import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.ddl.impl.SecurityLabelStmtStatementAssert; import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.ddl.impl.TruncateStatementAssert; import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.ddl.impl.UnlistenStatementAssert; +import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.ddl.impl.sqlserver.SQLServerUpdateStatisticsStatementAssert; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.AlterIndexStatementTestCase; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.AlterSessionStatementTestCase; @@ -124,6 +126,7 @@ import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.SecurityLabelStmtStatementTestCase; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.TruncateStatementTestCase; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.UnlistenStatementTestCase; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.UpdateStatisticsStatementTestCase; /** * DDL statement assert. @@ -207,6 +210,8 @@ public static void assertIs(final SQLCaseAssertContext assertContext, final DDLS AlterTablespaceStatementAssert.assertIs(assertContext, (AlterTablespaceStatement) actual, (AlterTablespaceStatementTestCase) expected); } else if (actual instanceof CreateSequenceStatement) { CreateSequenceStatementAssert.assertIs(assertContext, (CreateSequenceStatement) actual, (CreateSequenceStatementTestCase) expected); + } else if (actual instanceof SQLServerUpdateStatisticsStatement) { + SQLServerUpdateStatisticsStatementAssert.assertIs(assertContext, (SQLServerUpdateStatisticsStatement) actual, (UpdateStatisticsStatementTestCase) expected); } } } diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/ddl/impl/sqlserver/SQLServerUpdateStatisticsStatementAssert.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/ddl/impl/sqlserver/SQLServerUpdateStatisticsStatementAssert.java new file mode 100644 index 0000000000000..f737002729985 --- /dev/null +++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/ddl/impl/sqlserver/SQLServerUpdateStatisticsStatementAssert.java @@ -0,0 +1,83 @@ +/* + * 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.it.sql.parser.internal.asserts.statement.ddl.impl.sqlserver; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.ddl.SQLServerUpdateStatisticsStatement; +import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.SQLCaseAssertContext; +import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.index.IndexAssert; +import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.statistics.StatisticsStrategyAssert; +import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.table.TableAssert; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.index.ExpectedIndex; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.UpdateStatisticsStatementTestCase; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +/** + * Update statistics statement assert. + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class SQLServerUpdateStatisticsStatementAssert { + + /** + * Assert update statistics statement is correct with expected parser result. + * + * @param assertContext assert context + * @param actual actual update statistics statement + * @param expected expected update statistics statement test case + */ + public static void assertIs(final SQLCaseAssertContext assertContext, final SQLServerUpdateStatisticsStatement actual, final UpdateStatisticsStatementTestCase expected) { + assertTable(assertContext, actual, expected); + assertIndex(assertContext, actual, expected); + assertStrategy(assertContext, actual, expected); + } + + private static void assertTable(final SQLCaseAssertContext assertContext, final SQLServerUpdateStatisticsStatement actual, final UpdateStatisticsStatementTestCase expected) { + if (null == expected.getTable()) { + assertNull(actual.getTable(), assertContext.getText("Actual table segment should not exist.")); + } else { + assertNotNull(actual.getTable(), assertContext.getText("Actual table segment should exist.")); + TableAssert.assertIs(assertContext, actual.getTable(), expected.getTable()); + } + } + + private static void assertIndex(final SQLCaseAssertContext assertContext, final SQLServerUpdateStatisticsStatement actual, final UpdateStatisticsStatementTestCase expected) { + if (null == expected.getIndexes()) { + assertNull(actual.getIndexes(), assertContext.getText("Actual index segment should not exist.")); + } else { + int count = 0; + assertNotNull(actual.getIndexes(), assertContext.getText("Actual index segment should exist.")); + for (ExpectedIndex index : expected.getIndexes()) { + IndexAssert.assertIs(assertContext, actual.getIndexes().get(count), index); + count++; + } + } + } + + private static void assertStrategy(final SQLCaseAssertContext assertContext, final SQLServerUpdateStatisticsStatement actual, final UpdateStatisticsStatementTestCase expected) { + if (null == expected.getStrategy()) { + assertNull(actual.getStrategy(), assertContext.getText("Actual strategy segment should not exist.")); + } else { + assertNotNull(actual.getStrategy(), assertContext.getText("Actual strategy segment should exist.")); + StatisticsStrategyAssert.assertIs(assertContext, actual.getStrategy(), expected.getStrategy()); + } + } + +} diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/RootSQLParserTestCases.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/RootSQLParserTestCases.java index 8406f46775be5..869b7b5062340 100644 --- a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/RootSQLParserTestCases.java +++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/RootSQLParserTestCases.java @@ -290,6 +290,7 @@ import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.SwitchStatementTestCase; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.TruncateStatementTestCase; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.UnlistenStatementTestCase; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.UpdateStatisticsStatementTestCase; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dml.CallStatementTestCase; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dml.CheckpointStatementTestCase; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dml.CopyStatementTestCase; @@ -1736,6 +1737,9 @@ public final class RootSQLParserTestCases { @XmlElement(name = "create-profile") private final List createProfileStatementTestCases = new LinkedList<>(); + @XmlElement(name = "update-statistics") + private final List updateStatisticsStatementTestCases = new LinkedList<>(); + /** * Get all SQL parser test cases. * diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/statistics/ExpectedSampleOption.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/statistics/ExpectedSampleOption.java new file mode 100644 index 0000000000000..812cd96de1c48 --- /dev/null +++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/statistics/ExpectedSampleOption.java @@ -0,0 +1,46 @@ +/* + * 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.it.sql.parser.internal.cases.parser.jaxb.segment.impl.statistics; + +import lombok.Getter; +import lombok.Setter; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment; + +import javax.xml.bind.annotation.XmlAttribute; +import java.util.Collection; + +@Getter +@Setter +public final class ExpectedSampleOption extends AbstractExpectedSQLSegment { + + @XmlAttribute + private String strategy; + + @XmlAttribute + private Collection partitions; + + @XmlAttribute(name = "sample-number") + private String sampleNumber; + + @XmlAttribute(name = "persist-sample-percent") + private boolean persistSamplePercent; + + @XmlAttribute(name = "scan-unit") + private String scanUnit; + +} diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/statistics/ExpectedStatisticsOption.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/statistics/ExpectedStatisticsOption.java new file mode 100644 index 0000000000000..2b626f8f08414 --- /dev/null +++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/statistics/ExpectedStatisticsOption.java @@ -0,0 +1,44 @@ +/* + * 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.it.sql.parser.internal.cases.parser.jaxb.segment.impl.statistics; + +import lombok.Getter; +import lombok.Setter; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment; + +import javax.xml.bind.annotation.XmlAttribute; + +@Getter +@Setter +public final class ExpectedStatisticsOption extends AbstractExpectedSQLSegment { + + @XmlAttribute + private boolean incremental; + + @XmlAttribute(name = "statistics-dimension") + private String statisticsDimension; + + @XmlAttribute(name = "max-degree-of-parallelism") + private String maxDegreeOfParallelism; + + @XmlAttribute(name = "no-recompute") + private boolean noRecompute; + + @XmlAttribute(name = "auto-drop") + private boolean autoDrop; +} diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/statistics/ExpectedStatisticsStrategy.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/statistics/ExpectedStatisticsStrategy.java new file mode 100644 index 0000000000000..c95ca44615b1c --- /dev/null +++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/statistics/ExpectedStatisticsStrategy.java @@ -0,0 +1,35 @@ +/* + * 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.it.sql.parser.internal.cases.parser.jaxb.segment.impl.statistics; + +import lombok.Getter; +import lombok.Setter; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment; + +import javax.xml.bind.annotation.XmlElement; + +@Getter +@Setter +public final class ExpectedStatisticsStrategy extends AbstractExpectedSQLSegment { + + @XmlElement(name = "sample-option") + private ExpectedSampleOption sampleOption; + + @XmlElement(name = "statistics-option") + private ExpectedStatisticsOption statisticsOption; +} diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/UpdateStatisticsStatementTestCase.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/UpdateStatisticsStatementTestCase.java new file mode 100644 index 0000000000000..5ca46c0fb6f85 --- /dev/null +++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/UpdateStatisticsStatementTestCase.java @@ -0,0 +1,42 @@ +/* + * 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.it.sql.parser.internal.cases.parser.jaxb.statement.ddl; + +import lombok.Getter; +import lombok.Setter; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.index.ExpectedIndex; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.statistics.ExpectedStatisticsStrategy; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.table.ExpectedSimpleTable; + +import javax.xml.bind.annotation.XmlElement; +import java.util.Collection; + +@Getter +@Setter +public final class UpdateStatisticsStatementTestCase extends SQLParserTestCase { + + @XmlElement(name = "index") + private Collection indexes; + + @XmlElement(name = "table") + private ExpectedSimpleTable table; + + @XmlElement(name = "strategy") + private ExpectedStatisticsStrategy strategy; +} diff --git a/test/it/parser/src/main/resources/case/ddl/update-statistics.xml b/test/it/parser/src/main/resources/case/ddl/update-statistics.xml new file mode 100644 index 0000000000000..4b526e884fa1f --- /dev/null +++ b/test/it/parser/src/main/resources/case/ddl/update-statistics.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + +
+ + + + + + + +
+ +
+ + + + +
+ + + + +
+
+ + + + +
+ + + + + +
+ + + + +
+ + + + +
+
diff --git a/test/it/parser/src/main/resources/case/dml/select-join.xml b/test/it/parser/src/main/resources/case/dml/select-join.xml index 5c3bf47e084b2..479dde0011365 100644 --- a/test/it/parser/src/main/resources/case/dml/select-join.xml +++ b/test/it/parser/src/main/resources/case/dml/select-join.xml @@ -902,4 +902,185 @@ + + + + + + diff --git a/test/it/parser/src/main/resources/sql/supported/ddl/update-statistics.xml b/test/it/parser/src/main/resources/sql/supported/ddl/update-statistics.xml new file mode 100644 index 0000000000000..2503c0ec5a82c --- /dev/null +++ b/test/it/parser/src/main/resources/sql/supported/ddl/update-statistics.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + diff --git a/test/it/parser/src/main/resources/sql/supported/dml/select-join.xml b/test/it/parser/src/main/resources/sql/supported/dml/select-join.xml index a5b9ce05371eb..7a6fae3f09a79 100644 --- a/test/it/parser/src/main/resources/sql/supported/dml/select-join.xml +++ b/test/it/parser/src/main/resources/sql/supported/dml/select-join.xml @@ -36,4 +36,7 @@ + + +