diff --git a/async-query-core/src/main/java/org/opensearch/sql/spark/validator/GrammarElement.java b/async-query-core/src/main/java/org/opensearch/sql/spark/validator/GrammarElement.java index 05d878e9dc..3ee33d38fa 100644 --- a/async-query-core/src/main/java/org/opensearch/sql/spark/validator/GrammarElement.java +++ b/async-query-core/src/main/java/org/opensearch/sql/spark/validator/GrammarElement.java @@ -33,6 +33,7 @@ enum GrammarElement { HAVING("HAVING"), HINTS("HINTS"), INLINE_TABLE("Inline Table(VALUES)"), + FILE("File"), INNER_JOIN("INNER JOIN"), CROSS_JOIN("CROSS JOIN"), LEFT_OUTER_JOIN("LEFT OUTER JOIN"), diff --git a/async-query-core/src/main/java/org/opensearch/sql/spark/validator/GrammarElementValidatorFactory.java b/async-query-core/src/main/java/org/opensearch/sql/spark/validator/GrammarElementValidatorFactory.java index bd297c7afa..71f989e456 100644 --- a/async-query-core/src/main/java/org/opensearch/sql/spark/validator/GrammarElementValidatorFactory.java +++ b/async-query-core/src/main/java/org/opensearch/sql/spark/validator/GrammarElementValidatorFactory.java @@ -17,6 +17,7 @@ public class GrammarElementValidatorFactory { private static final Set DEFAULT_DENY_LIST = ImmutableSet.of(CREATE_FUNCTION, DROP_FUNCTION, INSERT, LOAD, HINTS, TABLESAMPLE); + // Deny List for CloudWatch Logs datasource private static final Set CWL_DENY_LIST = copyBuilder(DEFAULT_DENY_LIST) .add( @@ -71,18 +72,53 @@ public class GrammarElementValidatorFactory { UDF) .build(); + // Deny list for S3 Glue datasource private static final Set S3GLUE_DENY_LIST = copyBuilder(DEFAULT_DENY_LIST) .add( ALTER_VIEW, CREATE_VIEW, DROP_VIEW, - REPAIR_TABLE, DISTRIBUTE_BY, INLINE_TABLE, + CLUSTER_BY, + DISTRIBUTE_BY, + CROSS_JOIN, + LEFT_SEMI_JOIN, + RIGHT_OUTER_JOIN, + FULL_OUTER_JOIN, + LEFT_ANTI_JOIN, + TABLESAMPLE, + TABLE_VALUED_FUNCTION, + TRANSFORM, + MANAGE_RESOURCE, + DESCRIBE_FUNCTION, + REFRESH_RESOURCE, + REFRESH_FUNCTION, + RESET, + SET, + SHOW_FUNCTIONS, + SHOW_VIEWS, + MISC_FUNCTIONS, + UDF) + .build(); + + // Deny list for Security Lake datasource + private static final Set SL_DENY_LIST = + copyBuilder(DEFAULT_DENY_LIST) + .add( + ALTER_NAMESPACE, + ALTER_VIEW, + CREATE_NAMESPACE, + CREATE_VIEW, + DROP_NAMESPACE, + DROP_VIEW, + REPAIR_TABLE, TRUNCATE_TABLE, CLUSTER_BY, DISTRIBUTE_BY, + HINTS, + INLINE_TABLE, CROSS_JOIN, LEFT_SEMI_JOIN, RIGHT_OUTER_JOIN, @@ -92,19 +128,39 @@ public class GrammarElementValidatorFactory { TABLE_VALUED_FUNCTION, TRANSFORM, MANAGE_RESOURCE, + ANALYZE_TABLE, + CACHE_TABLE, + CLEAR_CACHE, + DESCRIBE_NAMESPACE, DESCRIBE_FUNCTION, + DESCRIBE_QUERY, + DESCRIBE_TABLE, REFRESH_RESOURCE, + REFRESH_TABLE, REFRESH_FUNCTION, RESET, SET, + SHOW_COLUMNS, + SHOW_CREATE_TABLE, + SHOW_NAMESPACES, SHOW_FUNCTIONS, + SHOW_PARTITIONS, + SHOW_TABLE_EXTENDED, + SHOW_TABLES, + SHOW_TBLPROPERTIES, SHOW_VIEWS, + UNCACHE_TABLE, + CSV_FUNCTIONS, MISC_FUNCTIONS, UDF) .build(); + private static Map validatorMap = - ImmutableMap.of(DataSourceType.S3GLUE, new DenyListGrammarElementValidator(S3GLUE_DENY_LIST)); + ImmutableMap.of( + DataSourceType.S3GLUE, new DenyListGrammarElementValidator(S3GLUE_DENY_LIST), + DataSourceType.SECURITY_LAKE, new DenyListGrammarElementValidator(SL_DENY_LIST) + ); public GrammarElementValidator getValidatorForDatasource(DataSourceType dataSourceType) { return validatorMap.get(dataSourceType); diff --git a/async-query-core/src/main/java/org/opensearch/sql/spark/validator/SQLQueryValidator.java b/async-query-core/src/main/java/org/opensearch/sql/spark/validator/SQLQueryValidator.java index 6c84be2a57..14d7b1ce22 100644 --- a/async-query-core/src/main/java/org/opensearch/sql/spark/validator/SQLQueryValidator.java +++ b/async-query-core/src/main/java/org/opensearch/sql/spark/validator/SQLQueryValidator.java @@ -8,6 +8,10 @@ import lombok.AllArgsConstructor; import org.antlr.v4.runtime.tree.TerminalNode; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser; +import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.AddTableColumnsContext; +import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.AddTablePartitionContext; +import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.AlterClusterByContext; +import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.AlterTableAlterColumnContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.AlterViewQueryContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.AlterViewSchemaBindingContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.AnalyzeContext; @@ -16,6 +20,8 @@ import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.ClearCacheContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.ClusterBySpecContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.CreateNamespaceContext; +import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.CreateTableContext; +import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.CreateTableLikeContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.CreateViewContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.CtesContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.DescribeFunctionContext; @@ -24,11 +30,15 @@ import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.DescribeRelationContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.DropFunctionContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.DropNamespaceContext; +import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.DropTableColumnsContext; +import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.DropTableContext; +import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.DropTablePartitionsContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.DropViewContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.ExplainContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.FunctionIdentifierContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.FunctionNameContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.HintContext; +import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.HiveReplaceColumnsContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.InlineTableContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.InsertIntoReplaceWhereContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.InsertIntoTableContext; @@ -41,11 +51,16 @@ import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.LoadDataContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.ManageResourceContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.QueryOrganizationContext; +import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.RecoverPartitionsContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.RefreshFunctionContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.RefreshResourceContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.RefreshTableContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.RelationContext; +import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.RenameTableColumnContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.RenameTableContext; +import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.RenameTablePartitionContext; +import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.RepairTableContext; +import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.ReplaceTableContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.ResetConfigurationContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.ResetQuotedConfigurationContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.SampleContext; @@ -53,6 +68,8 @@ import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.SetNamespaceLocationContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.SetNamespacePropertiesContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.SetQuantifierContext; +import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.SetTableLocationContext; +import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.SetTableSerDeContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.ShowColumnsContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.ShowCreateTableContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.ShowFunctionsContext; @@ -64,6 +81,7 @@ import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.ShowViewsContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.TableValuedFunctionContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.TransformClauseContext; +import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.TruncateTableContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.UncacheTableContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParser.UnsetNamespacePropertiesContext; import org.opensearch.sql.spark.antlr.parser.SqlBaseParserBaseVisitor; @@ -94,6 +112,80 @@ public Void visitUnsetNamespaceProperties(UnsetNamespacePropertiesContext ctx) { return super.visitUnsetNamespaceProperties(ctx); } + @Override + public Void visitAddTableColumns(AddTableColumnsContext ctx) { + validateAllowed(GrammarElement.ALTER_NAMESPACE); + return super.visitAddTableColumns(ctx); + } + + @Override + public Void visitAddTablePartition(AddTablePartitionContext ctx) { + validateAllowed(GrammarElement.ALTER_NAMESPACE); + return super.visitAddTablePartition(ctx); + } + + @Override + public Void visitRenameTableColumn(RenameTableColumnContext ctx) { + validateAllowed(GrammarElement.ALTER_NAMESPACE); + return super.visitRenameTableColumn(ctx); + } + + @Override + public Void visitDropTableColumns(DropTableColumnsContext ctx) { + validateAllowed(GrammarElement.ALTER_NAMESPACE); + return super.visitDropTableColumns(ctx); + } + + @Override + public Void visitAlterTableAlterColumn(AlterTableAlterColumnContext ctx) { + validateAllowed(GrammarElement.ALTER_NAMESPACE); + return super.visitAlterTableAlterColumn(ctx); + } + + @Override + public Void visitHiveReplaceColumns(HiveReplaceColumnsContext ctx) { + validateAllowed(GrammarElement.ALTER_NAMESPACE); + return super.visitHiveReplaceColumns(ctx); + } + + @Override + public Void visitSetTableSerDe(SetTableSerDeContext ctx) { + validateAllowed(GrammarElement.ALTER_NAMESPACE); + return super.visitSetTableSerDe(ctx); + } + + @Override + public Void visitRenameTablePartition(RenameTablePartitionContext ctx) { + validateAllowed(GrammarElement.ALTER_NAMESPACE); + return super.visitRenameTablePartition(ctx); + } + + @Override + public Void visitDropTablePartitions(DropTablePartitionsContext ctx) { + validateAllowed(GrammarElement.ALTER_NAMESPACE); + return super.visitDropTablePartitions(ctx); + } + + @Override + public Void visitSetTableLocation(SetTableLocationContext ctx) { + validateAllowed(GrammarElement.ALTER_NAMESPACE); + return super.visitSetTableLocation(ctx); + } + + @Override + public Void visitRecoverPartitions(RecoverPartitionsContext ctx) { + validateAllowed(GrammarElement.ALTER_NAMESPACE); + return super.visitRecoverPartitions(ctx); + } + + @Override + public Void visitAlterClusterBy(AlterClusterByContext ctx) { + validateAllowed(GrammarElement.ALTER_NAMESPACE); + return super.visitAlterClusterBy(ctx); + } + + + @Override public Void visitSetNamespaceLocation(SetNamespaceLocationContext ctx) { validateAllowed(GrammarElement.ALTER_NAMESPACE); @@ -131,12 +223,36 @@ public Void visitCreateNamespace(CreateNamespaceContext ctx) { return super.visitCreateNamespace(ctx); } + @Override + public Void visitCreateTable(CreateTableContext ctx) { + validateAllowed(GrammarElement.CREATE_NAMESPACE); + return super.visitCreateTable(ctx); + } + + @Override + public Void visitCreateTableLike(CreateTableLikeContext ctx) { + validateAllowed(GrammarElement.CREATE_NAMESPACE); + return super.visitCreateTableLike(ctx); + } + + @Override + public Void visitReplaceTable(ReplaceTableContext ctx) { + validateAllowed(GrammarElement.CREATE_NAMESPACE); + return super.visitReplaceTable(ctx); + } + @Override public Void visitDropNamespace(DropNamespaceContext ctx) { validateAllowed(GrammarElement.DROP_NAMESPACE); return super.visitDropNamespace(ctx); } + @Override + public Void visitDropTable(DropTableContext ctx) { + validateAllowed(GrammarElement.DROP_NAMESPACE); + return super.visitDropTable(ctx); + } + @Override public Void visitCreateView(CreateViewContext ctx) { validateAllowed(GrammarElement.CREATE_VIEW); @@ -155,6 +271,18 @@ public Void visitDropFunction(DropFunctionContext ctx) { return super.visitDropFunction(ctx); } + @Override + public Void visitRepairTable(RepairTableContext ctx) { + validateAllowed(GrammarElement.REPAIR_TABLE); + return super.visitRepairTable(ctx); + } + + @Override + public Void visitTruncateTable(TruncateTableContext ctx) { + validateAllowed(GrammarElement.TRUNCATE_TABLE); + return super.visitTruncateTable(ctx); + } + @Override public Void visitInsertOverwriteTable(InsertOverwriteTableContext ctx) { validateAllowed(GrammarElement.INSERT); diff --git a/async-query-core/src/test/java/org/opensearch/sql/spark/validator/SQLQueryValidatorTest.java b/async-query-core/src/test/java/org/opensearch/sql/spark/validator/SQLQueryValidatorTest.java index 88fe273aec..53a9a94a57 100644 --- a/async-query-core/src/test/java/org/opensearch/sql/spark/validator/SQLQueryValidatorTest.java +++ b/async-query-core/src/test/java/org/opensearch/sql/spark/validator/SQLQueryValidatorTest.java @@ -164,138 +164,267 @@ public String toString() { @Test void s3glueQueries() { - SQLQueryValidator v = - new SQLQueryValidator(factory.getValidatorForDatasource(DataSourceType.S3GLUE)); - verifyValid(v, TestQuery.ALTER_DATABASE); - verifyValid(v, TestQuery.ALTER_TABLE); - verifyInvalid(v, TestQuery.ALTER_VIEW); - verifyValid(v, TestQuery.CREATE_DATABASE); - verifyInvalid(v, TestQuery.CREATE_FUNCTION); - verifyValid(v, TestQuery.CREATE_TABLE); - verifyInvalid(v, TestQuery.CREATE_VIEW); - verifyValid(v, TestQuery.DROP_DATABASE); - verifyInvalid(v, TestQuery.DROP_FUNCTION); - verifyValid(v, TestQuery.DROP_TABLE); - verifyInvalid(v, TestQuery.DROP_VIEW); - verifyValid(v, TestQuery.REPAIR_TABLE); - verifyValid(v, TestQuery.TRUNCATE_TABLE); + VerifyValidator v = new VerifyValidator(new SQLQueryValidator(factory.getValidatorForDatasource(DataSourceType.S3GLUE))); + // DDL Statements + v.ok(TestQuery.ALTER_DATABASE); + v.ok(TestQuery.ALTER_TABLE); + v.ng(TestQuery.ALTER_VIEW); + v.ok(TestQuery.CREATE_DATABASE); + v.ng(TestQuery.CREATE_FUNCTION); + v.ok(TestQuery.CREATE_TABLE); + v.ng(TestQuery.CREATE_VIEW); + v.ok(TestQuery.DROP_DATABASE); + v.ng(TestQuery.DROP_FUNCTION); + v.ok(TestQuery.DROP_TABLE); + v.ng(TestQuery.DROP_VIEW); + v.ok(TestQuery.REPAIR_TABLE); + v.ok(TestQuery.TRUNCATE_TABLE); // DML Statements - verifyInvalid(v, TestQuery.INSERT_TABLE); - verifyInvalid(v, TestQuery.INSERT_OVERWRITE_DIRECTORY); - verifyInvalid(v, TestQuery.LOAD); + v.ng(TestQuery.INSERT_TABLE); + v.ng(TestQuery.INSERT_OVERWRITE_DIRECTORY); + v.ng(TestQuery.LOAD); // Data Retrieval - verifyValid(v, TestQuery.SELECT); - verifyValid(v, TestQuery.EXPLAIN); - verifyValid(v, TestQuery.COMMON_TABLE_EXPRESSION); - verifyInvalid(v, TestQuery.CLUSTER_BY_CLAUSE); - verifyInvalid(v, TestQuery.DISTRIBUTE_BY_CLAUSE); - verifyValid(v, TestQuery.GROUP_BY_CLAUSE); - verifyValid(v, TestQuery.HAVING_CLAUSE); - verifyInvalid(v, TestQuery.HINTS); - verifyInvalid(v, TestQuery.INLINE_TABLE); - // verifyInvalid(v, TestQuery.FILE); TODO: need dive deep - verifyValid(v, TestQuery.INNER_JOIN); - verifyInvalid(v, TestQuery.CROSS_JOIN); - verifyValid(v, TestQuery.LEFT_OUTER_JOIN); - verifyInvalid(v, TestQuery.LEFT_SEMI_JOIN); - verifyInvalid(v, TestQuery.RIGHT_OUTER_JOIN); - verifyInvalid(v, TestQuery.FULL_OUTER_JOIN); - verifyInvalid(v, TestQuery.LEFT_ANTI_JOIN); - verifyValid(v, TestQuery.LIKE_PREDICATE); - verifyValid(v, TestQuery.LIMIT_CLAUSE); - verifyValid(v, TestQuery.OFFSET_CLAUSE); - verifyValid(v, TestQuery.ORDER_BY_CLAUSE); - verifyValid(v, TestQuery.SET_OPERATORS); - verifyValid(v, TestQuery.SORT_BY_CLAUSE); - verifyInvalid(v, TestQuery.TABLESAMPLE); - verifyInvalid(v, TestQuery.TABLE_VALUED_FUNCTION); - verifyValid(v, TestQuery.WHERE_CLAUSE); - verifyValid(v, TestQuery.AGGREGATE_FUNCTION); - verifyValid(v, TestQuery.WINDOW_FUNCTION); - verifyValid(v, TestQuery.CASE_CLAUSE); - verifyValid(v, TestQuery.PIVOT_CLAUSE); - verifyValid(v, TestQuery.UNPIVOT_CLAUSE); - verifyValid(v, TestQuery.LATERAL_VIEW_CLAUSE); - verifyValid(v, TestQuery.LATERAL_SUBQUERY); - verifyInvalid(v, TestQuery.TRANSFORM_CLAUSE); + v.ok(TestQuery.SELECT); + v.ok(TestQuery.EXPLAIN); + v.ok(TestQuery.COMMON_TABLE_EXPRESSION); + v.ng(TestQuery.CLUSTER_BY_CLAUSE); + v.ng(TestQuery.DISTRIBUTE_BY_CLAUSE); + v.ok(TestQuery.GROUP_BY_CLAUSE); + v.ok(TestQuery.HAVING_CLAUSE); + v.ng(TestQuery.HINTS); + v.ng(TestQuery.INLINE_TABLE); + // v.ng(TestQuery.FILE); TODO: need dive deep + v.ok(TestQuery.INNER_JOIN); + v.ng(TestQuery.CROSS_JOIN); + v.ok(TestQuery.LEFT_OUTER_JOIN); + v.ng(TestQuery.LEFT_SEMI_JOIN); + v.ng(TestQuery.RIGHT_OUTER_JOIN); + v.ng(TestQuery.FULL_OUTER_JOIN); + v.ng(TestQuery.LEFT_ANTI_JOIN); + v.ok(TestQuery.LIKE_PREDICATE); + v.ok(TestQuery.LIMIT_CLAUSE); + v.ok(TestQuery.OFFSET_CLAUSE); + v.ok(TestQuery.ORDER_BY_CLAUSE); + v.ok(TestQuery.SET_OPERATORS); + v.ok(TestQuery.SORT_BY_CLAUSE); + v.ng(TestQuery.TABLESAMPLE); + v.ng(TestQuery.TABLE_VALUED_FUNCTION); + v.ok(TestQuery.WHERE_CLAUSE); + v.ok(TestQuery.AGGREGATE_FUNCTION); + v.ok(TestQuery.WINDOW_FUNCTION); + v.ok(TestQuery.CASE_CLAUSE); + v.ok(TestQuery.PIVOT_CLAUSE); + v.ok(TestQuery.UNPIVOT_CLAUSE); + v.ok(TestQuery.LATERAL_VIEW_CLAUSE); + v.ok(TestQuery.LATERAL_SUBQUERY); + v.ng(TestQuery.TRANSFORM_CLAUSE); // Auxiliary Statements - verifyInvalid(v, TestQuery.ADD_FILE); - verifyInvalid(v, TestQuery.ADD_JAR); - verifyValid(v, TestQuery.ANALYZE_TABLE); - verifyValid(v, TestQuery.CACHE_TABLE); - verifyValid(v, TestQuery.CLEAR_CACHE); - verifyValid(v, TestQuery.DESCRIBE_DATABASE); - verifyInvalid(v, TestQuery.DESCRIBE_FUNCTION); - verifyValid(v, TestQuery.DESCRIBE_QUERY); - verifyValid(v, TestQuery.DESCRIBE_TABLE); - verifyInvalid(v, TestQuery.LIST_FILE); - verifyInvalid(v, TestQuery.LIST_JAR); - verifyInvalid(v, TestQuery.REFRESH); - // verifyValid(v, TestQuery.REFRESH_TABLE); TODO: refreshTable rule won't match (matches to + v.ng(TestQuery.ADD_FILE); + v.ng(TestQuery.ADD_JAR); + v.ok(TestQuery.ANALYZE_TABLE); + v.ok(TestQuery.CACHE_TABLE); + v.ok(TestQuery.CLEAR_CACHE); + v.ok(TestQuery.DESCRIBE_DATABASE); + v.ng(TestQuery.DESCRIBE_FUNCTION); + v.ok(TestQuery.DESCRIBE_QUERY); + v.ok(TestQuery.DESCRIBE_TABLE); + v.ng(TestQuery.LIST_FILE); + v.ng(TestQuery.LIST_JAR); + v.ng(TestQuery.REFRESH); + // v.ok(TestQuery.REFRESH_TABLE); TODO: refreshTable rule won't match (matches to // refreshResource) - verifyInvalid(v, TestQuery.REFRESH_FUNCTION); - verifyInvalid(v, TestQuery.RESET); - verifyInvalid(v, TestQuery.SET); - verifyValid(v, TestQuery.SHOW_COLUMNS); - verifyValid(v, TestQuery.SHOW_CREATE_TABLE); - verifyValid(v, TestQuery.SHOW_DATABASES); - verifyInvalid(v, TestQuery.SHOW_FUNCTIONS); - verifyValid(v, TestQuery.SHOW_PARTITIONS); - verifyValid(v, TestQuery.SHOW_TABLE_EXTENDED); - verifyValid(v, TestQuery.SHOW_TABLES); - verifyValid(v, TestQuery.SHOW_TBLPROPERTIES); - verifyInvalid(v, TestQuery.SHOW_VIEWS); - verifyValid(v, TestQuery.UNCACHE_TABLE); + v.ng(TestQuery.REFRESH_FUNCTION); + v.ng(TestQuery.RESET); + v.ng(TestQuery.SET); + v.ok(TestQuery.SHOW_COLUMNS); + v.ok(TestQuery.SHOW_CREATE_TABLE); + v.ok(TestQuery.SHOW_DATABASES); + v.ng(TestQuery.SHOW_FUNCTIONS); + v.ok(TestQuery.SHOW_PARTITIONS); + v.ok(TestQuery.SHOW_TABLE_EXTENDED); + v.ok(TestQuery.SHOW_TABLES); + v.ok(TestQuery.SHOW_TBLPROPERTIES); + v.ng(TestQuery.SHOW_VIEWS); + v.ok(TestQuery.UNCACHE_TABLE); // Functions - verifyValid(v, TestQuery.ARRAY_FUNCTIONS); - verifyValid(v, TestQuery.MAP_FUNCTIONS); - verifyValid(v, TestQuery.DATE_AND_TIMESTAMP_FUNCTIONS); - verifyValid(v, TestQuery.JSON_FUNCTIONS); - verifyValid(v, TestQuery.MATHEMATICAL_FUNCTIONS); - verifyValid(v, TestQuery.STRING_FUNCTIONS); - verifyValid(v, TestQuery.BITWISE_FUNCTIONS); - verifyValid(v, TestQuery.CONVERSION_FUNCTIONS); - verifyValid(v, TestQuery.CONDITIONAL_FUNCTIONS); - verifyValid(v, TestQuery.PREDICATE_FUNCTIONS); - verifyValid(v, TestQuery.CSV_FUNCTIONS); - verifyInvalid(v, TestQuery.MISC_FUNCTIONS); + v.ok(TestQuery.ARRAY_FUNCTIONS); + v.ok(TestQuery.MAP_FUNCTIONS); + v.ok(TestQuery.DATE_AND_TIMESTAMP_FUNCTIONS); + v.ok(TestQuery.JSON_FUNCTIONS); + v.ok(TestQuery.MATHEMATICAL_FUNCTIONS); + v.ok(TestQuery.STRING_FUNCTIONS); + v.ok(TestQuery.BITWISE_FUNCTIONS); + v.ok(TestQuery.CONVERSION_FUNCTIONS); + v.ok(TestQuery.CONDITIONAL_FUNCTIONS); + v.ok(TestQuery.PREDICATE_FUNCTIONS); + v.ok(TestQuery.CSV_FUNCTIONS); + v.ng(TestQuery.MISC_FUNCTIONS); // Aggregate-like Functions - verifyValid(v, TestQuery.AGGREGATE_FUNCTIONS); - verifyValid(v, TestQuery.WINDOW_FUNCTIONS); + v.ok(TestQuery.AGGREGATE_FUNCTIONS); + v.ok(TestQuery.WINDOW_FUNCTIONS); // Generator Functions - verifyValid(v, TestQuery.GENERATOR_FUNCTIONS); + v.ok(TestQuery.GENERATOR_FUNCTIONS); // UDFs - verifyInvalid(v, TestQuery.SCALAR_USER_DEFINED_FUNCTIONS); - verifyInvalid(v, TestQuery.USER_DEFINED_AGGREGATE_FUNCTIONS); - verifyInvalid(v, TestQuery.INTEGRATION_WITH_HIVE_UDFS_UDAFS_UDTFS); + v.ng(TestQuery.SCALAR_USER_DEFINED_FUNCTIONS); + v.ng(TestQuery.USER_DEFINED_AGGREGATE_FUNCTIONS); + v.ng(TestQuery.INTEGRATION_WITH_HIVE_UDFS_UDAFS_UDTFS); } - void verifyValid(SQLQueryValidator validator, TestQuery query) { - runValidate(validator, query.toString()); + @Test + void securityLakeQueries() { + VerifyValidator v = new VerifyValidator(new SQLQueryValidator(factory.getValidatorForDatasource(DataSourceType.SECURITY_LAKE))); + // DDL Statements + v.ng(TestQuery.ALTER_DATABASE); + v.ng(TestQuery.ALTER_TABLE); + v.ng(TestQuery.ALTER_VIEW); + v.ng(TestQuery.CREATE_DATABASE); + v.ng(TestQuery.CREATE_FUNCTION); + v.ng(TestQuery.CREATE_TABLE); + v.ng(TestQuery.CREATE_VIEW); + v.ng(TestQuery.DROP_DATABASE); + v.ng(TestQuery.DROP_FUNCTION); + v.ng(TestQuery.DROP_TABLE); + v.ng(TestQuery.DROP_VIEW); + v.ng(TestQuery.REPAIR_TABLE); + v.ng(TestQuery.TRUNCATE_TABLE); + + // DML Statements + v.ng(TestQuery.INSERT_TABLE); + v.ng(TestQuery.INSERT_OVERWRITE_DIRECTORY); + v.ng(TestQuery.LOAD); + + // Data Retrieval + v.ok(TestQuery.SELECT); + v.ok(TestQuery.EXPLAIN); + v.ok(TestQuery.COMMON_TABLE_EXPRESSION); + v.ng(TestQuery.CLUSTER_BY_CLAUSE); + v.ng(TestQuery.DISTRIBUTE_BY_CLAUSE); + v.ok(TestQuery.GROUP_BY_CLAUSE); + v.ok(TestQuery.HAVING_CLAUSE); + v.ng(TestQuery.HINTS); + v.ng(TestQuery.INLINE_TABLE); + // v.ng(TestQuery.FILE); TODO: need dive deep + v.ok(TestQuery.INNER_JOIN); + v.ng(TestQuery.CROSS_JOIN); + v.ok(TestQuery.LEFT_OUTER_JOIN); + v.ng(TestQuery.LEFT_SEMI_JOIN); + v.ng(TestQuery.RIGHT_OUTER_JOIN); + v.ng(TestQuery.FULL_OUTER_JOIN); + v.ng(TestQuery.LEFT_ANTI_JOIN); + v.ok(TestQuery.LIKE_PREDICATE); + v.ok(TestQuery.LIMIT_CLAUSE); + v.ok(TestQuery.OFFSET_CLAUSE); + v.ok(TestQuery.ORDER_BY_CLAUSE); + v.ok(TestQuery.SET_OPERATORS); + v.ok(TestQuery.SORT_BY_CLAUSE); + v.ng(TestQuery.TABLESAMPLE); + v.ng(TestQuery.TABLE_VALUED_FUNCTION); + v.ok(TestQuery.WHERE_CLAUSE); + v.ok(TestQuery.AGGREGATE_FUNCTION); + v.ok(TestQuery.WINDOW_FUNCTION); + v.ok(TestQuery.CASE_CLAUSE); + v.ok(TestQuery.PIVOT_CLAUSE); + v.ok(TestQuery.UNPIVOT_CLAUSE); + v.ok(TestQuery.LATERAL_VIEW_CLAUSE); + v.ok(TestQuery.LATERAL_SUBQUERY); + v.ng(TestQuery.TRANSFORM_CLAUSE); + + // Auxiliary Statements + v.ng(TestQuery.ADD_FILE); + v.ng(TestQuery.ADD_JAR); + v.ng(TestQuery.ANALYZE_TABLE); + v.ng(TestQuery.CACHE_TABLE); + v.ng(TestQuery.CLEAR_CACHE); + v.ng(TestQuery.DESCRIBE_DATABASE); + v.ng(TestQuery.DESCRIBE_FUNCTION); + v.ng(TestQuery.DESCRIBE_QUERY); + v.ng(TestQuery.DESCRIBE_TABLE); + v.ng(TestQuery.LIST_FILE); + v.ng(TestQuery.LIST_JAR); + v.ng(TestQuery.REFRESH); + // v.ng(TestQuery.REFRESH_TABLE); TODO: refreshTable rule won't match (matches to + // refreshResource) + v.ng(TestQuery.REFRESH_FUNCTION); + v.ng(TestQuery.RESET); + v.ng(TestQuery.SET); + v.ng(TestQuery.SHOW_COLUMNS); + v.ng(TestQuery.SHOW_CREATE_TABLE); + v.ng(TestQuery.SHOW_DATABASES); + v.ng(TestQuery.SHOW_FUNCTIONS); + v.ng(TestQuery.SHOW_PARTITIONS); + v.ng(TestQuery.SHOW_TABLE_EXTENDED); + v.ng(TestQuery.SHOW_TABLES); + v.ng(TestQuery.SHOW_TBLPROPERTIES); + v.ng(TestQuery.SHOW_VIEWS); + v.ng(TestQuery.UNCACHE_TABLE); + + // Functions + v.ok(TestQuery.ARRAY_FUNCTIONS); + v.ok(TestQuery.MAP_FUNCTIONS); + v.ok(TestQuery.DATE_AND_TIMESTAMP_FUNCTIONS); + v.ok(TestQuery.JSON_FUNCTIONS); + v.ok(TestQuery.MATHEMATICAL_FUNCTIONS); + v.ok(TestQuery.STRING_FUNCTIONS); + v.ok(TestQuery.BITWISE_FUNCTIONS); + v.ok(TestQuery.CONVERSION_FUNCTIONS); + v.ok(TestQuery.CONDITIONAL_FUNCTIONS); + v.ok(TestQuery.PREDICATE_FUNCTIONS); + v.ng(TestQuery.CSV_FUNCTIONS); + v.ng(TestQuery.MISC_FUNCTIONS); + + // Aggregate-like Functions + v.ok(TestQuery.AGGREGATE_FUNCTIONS); + v.ok(TestQuery.WINDOW_FUNCTIONS); + + // Generator Functions + v.ok(TestQuery.GENERATOR_FUNCTIONS); + + // UDFs + v.ng(TestQuery.SCALAR_USER_DEFINED_FUNCTIONS); + v.ng(TestQuery.USER_DEFINED_AGGREGATE_FUNCTIONS); + v.ng(TestQuery.INTEGRATION_WITH_HIVE_UDFS_UDAFS_UDTFS); } - void verifyInvalid(SQLQueryValidator validator, TestQuery query) { - assertThrows( - IllegalArgumentException.class, - () -> runValidate(validator, query.toString()), - "The query should throw: query=`" + query.toString() + "`"); + @AllArgsConstructor + private static class VerifyValidator { + private final SQLQueryValidator validator; + + public void ok(TestQuery query) { + runValidate(validator, query.toString()); + + } + + public void ng(TestQuery query) { + assertThrows( + IllegalArgumentException.class, + () -> runValidate(validator, query.toString()), + "The query should throw: query=`" + query.toString() + "`"); + } + + void runValidate(SQLQueryValidator validator, String query) { + validator.validate(getParser(query)); + } + + SingleStatementContext getParser(String query) { + SqlBaseParser sqlBaseParser = + new SqlBaseParser( + new CommonTokenStream(new SqlBaseLexer(new CaseInsensitiveCharStream(query)))); + return sqlBaseParser.singleStatement(); + } } - void runValidate(SQLQueryValidator validator, String query) { - validator.validate(getParser(query)); + void ok(SQLQueryValidator validator, TestQuery query) { } - SingleStatementContext getParser(String query) { - SqlBaseParser sqlBaseParser = - new SqlBaseParser( - new CommonTokenStream(new SqlBaseLexer(new CaseInsensitiveCharStream(query)))); - return sqlBaseParser.singleStatement(); + void ng(SQLQueryValidator validator, TestQuery query) { } + + }