diff --git a/zpa-checks/src/integrationTest/resources/expected/antlr-grammars-v4/ParsingErrorCheck.json b/zpa-checks/src/integrationTest/resources/expected/antlr-grammars-v4/ParsingErrorCheck.json index 814b05a6..7ee480e4 100644 --- a/zpa-checks/src/integrationTest/resources/expected/antlr-grammars-v4/ParsingErrorCheck.json +++ b/zpa-checks/src/integrationTest/resources/expected/antlr-grammars-v4/ParsingErrorCheck.json @@ -5,9 +5,6 @@ "examples-sql-script/grants.sql" : [ 5 ], - "examples-sql-script/green_table.sql" : [ - 6 - ], "examples-sql-script/logical_expressions.sql" : [ 13 ], diff --git a/zpa-checks/src/integrationTest/resources/expected/antlr-grammars-v4/SelectAllColumnsCheck.json b/zpa-checks/src/integrationTest/resources/expected/antlr-grammars-v4/SelectAllColumnsCheck.json index a10c98c1..3ff12457 100644 --- a/zpa-checks/src/integrationTest/resources/expected/antlr-grammars-v4/SelectAllColumnsCheck.json +++ b/zpa-checks/src/integrationTest/resources/expected/antlr-grammars-v4/SelectAllColumnsCheck.json @@ -1,4 +1,7 @@ { + "examples-sql-script/green_table.sql" : [ + 26 + ], "examples-sql-script/package_with_cursor.sql" : [ 4 ], diff --git a/zpa-checks/src/integrationTest/resources/expected/oracle-database_23/ParsingErrorCheck.json b/zpa-checks/src/integrationTest/resources/expected/oracle-database_23/ParsingErrorCheck.json index 31d40a6e..ebaefe1b 100644 --- a/zpa-checks/src/integrationTest/resources/expected/oracle-database_23/ParsingErrorCheck.json +++ b/zpa-checks/src/integrationTest/resources/expected/oracle-database_23/ParsingErrorCheck.json @@ -98,9 +98,6 @@ "adjsn/json-schema-16.sql" : [ 4 ], - "adjsn/json-schema-22.sql" : [ - 3 - ], "adjsn/json-schema-3.sql" : [ 2 ], @@ -1304,9 +1301,6 @@ "sqlrf/ALTER-TABLE-129.sql" : [ 3 ], - "sqlrf/ALTER-TABLE-16.sql" : [ - 5 - ], "sqlrf/ALTER-TABLE-17.sql" : [ 2 ], @@ -1334,9 +1328,6 @@ "sqlrf/ALTER-TABLE-27.sql" : [ 3 ], - "sqlrf/ALTER-TABLE-28.sql" : [ - 4 - ], "sqlrf/ALTER-TABLE-29.sql" : [ 3 ], @@ -2189,9 +2180,6 @@ "sqlrf/CREATE-TABLE-28.sql" : [ 3 ], - "sqlrf/CREATE-TABLE-30.sql" : [ - 4 - ], "sqlrf/CREATE-TABLE-31.sql" : [ 13 ], @@ -2912,15 +2900,6 @@ "sqlrf/constraint-1.sql" : [ 10 ], - "sqlrf/constraint-10.sql" : [ - 6 - ], - "sqlrf/constraint-11.sql" : [ - 5 - ], - "sqlrf/constraint-14.sql" : [ - 5 - ], "sqlrf/constraint-15.sql" : [ 2 ], @@ -2942,15 +2921,9 @@ "sqlrf/constraint-31.sql" : [ 10 ], - "sqlrf/constraint-33.sql" : [ - 4 - ], "sqlrf/constraint-5.sql" : [ 3 ], - "sqlrf/constraint-6.sql" : [ - 3 - ], "sqlrf/constraint-8.sql" : [ 10 ], diff --git a/zpa-core/src/main/kotlin/org/sonar/plugins/plsqlopen/api/DdlGrammar.kt b/zpa-core/src/main/kotlin/org/sonar/plugins/plsqlopen/api/DdlGrammar.kt index 723c5e0f..06637827 100644 --- a/zpa-core/src/main/kotlin/org/sonar/plugins/plsqlopen/api/DdlGrammar.kt +++ b/zpa-core/src/main/kotlin/org/sonar/plugins/plsqlopen/api/DdlGrammar.kt @@ -78,7 +78,10 @@ enum class DdlGrammar : GrammarRuleKey { SUBPARTITION_TEMPLATE, CREATE_DIRECTORY, DROP_DIRECTORY, - TRUNCATE_TABLE; + TRUNCATE_TABLE, + CONSTRAINT_STATE, + PRECHECK_STATE, + EXCEPTIONS_CLAUSE; companion object { fun buildOn(b: PlSqlGrammarBuilder) { @@ -115,13 +118,39 @@ enum class DdlGrammar : GrammarRuleKey { ) b.rule(INLINE_CONSTRAINT).define( - b.optional(CONSTRAINT, IDENTIFIER_NAME), - b.firstOf( + b.optional(CONSTRAINT, IDENTIFIER_NAME), + b.firstOf( + b.sequence( + b.firstOf( b.sequence(b.optional(NOT), NULL), UNIQUE, b.sequence(PRIMARY, KEY), - REFERENCES_CLAUSE, - b.sequence(CHECK, EXPRESSION))) + REFERENCES_CLAUSE + ), b.optional(CONSTRAINT_STATE) + ), + b.sequence( + CHECK, LPARENTHESIS, EXPRESSION, RPARENTHESIS, + b.optional(CONSTRAINT_STATE), + b.optional(PRECHECK_STATE) + ) + ) + ) + + b.rule(CONSTRAINT_STATE).define( + b.optional(b.firstOf( + b.sequence(INITIALLY, b.firstOf(DEFERRED, IMMEDIATE), b.optional(b.optional(NOT), DEFERRABLE)), + b.sequence(b.optional(NOT), DEFERRABLE, b.optional(INITIALLY, b.firstOf(DEFERRED, IMMEDIATE))), + )), + b.optional(b.firstOf(RELY, NORELY)), + // TODO b.optional(USING_INDEX_CLAUSE), + b.optional(b.firstOf(ENABLE, DISABLE)), + b.optional(b.firstOf(VALIDATE, NOVALIDATE)), + b.optional(EXCEPTIONS_CLAUSE) + ) + + b.rule(PRECHECK_STATE).define(b.firstOf(PRECHECK, NOPRECHECK)) + + b.rule(EXCEPTIONS_CLAUSE).define(EXCEPTIONS, INTO, UNIT_NAME) b.rule(TABLE_COLUMN_DEFINITION).define( IDENTIFIER_NAME, DATATYPE, @@ -131,12 +160,22 @@ enum class DdlGrammar : GrammarRuleKey { b.zeroOrMore(INLINE_CONSTRAINT)) b.rule(OUT_OF_LINE_CONSTRAINT).define( - b.optional(CONSTRAINT, IDENTIFIER_NAME), - b.firstOf( + b.optional(CONSTRAINT, IDENTIFIER_NAME), + b.firstOf( + b.sequence( + b.firstOf( b.sequence(UNIQUE, ONE_OR_MORE_IDENTIFIERS), b.sequence(PRIMARY, KEY, ONE_OR_MORE_IDENTIFIERS, b.optional(b.sequence(USING, INDEX))), - b.sequence(FOREIGN, KEY, ONE_OR_MORE_IDENTIFIERS, REFERENCES_CLAUSE), - b.sequence(CHECK, EXPRESSION))) + b.sequence(FOREIGN, KEY, ONE_OR_MORE_IDENTIFIERS, REFERENCES_CLAUSE) + ), b.optional(CONSTRAINT_STATE) + ), + b.sequence( + CHECK, LPARENTHESIS, EXPRESSION, RPARENTHESIS, + b.optional(CONSTRAINT_STATE), + b.optional(PRECHECK_STATE) + ) + ) + ) b.rule(TABLE_RELATIONAL_PROPERTIES).define( b.oneOrMore(b.firstOf(OUT_OF_LINE_CONSTRAINT, TABLE_COLUMN_DEFINITION), b.optional(COMMA))) diff --git a/zpa-core/src/main/kotlin/org/sonar/plugins/plsqlopen/api/PlSqlKeyword.kt b/zpa-core/src/main/kotlin/org/sonar/plugins/plsqlopen/api/PlSqlKeyword.kt index da358aa1..dac90f96 100644 --- a/zpa-core/src/main/kotlin/org/sonar/plugins/plsqlopen/api/PlSqlKeyword.kt +++ b/zpa-core/src/main/kotlin/org/sonar/plugins/plsqlopen/api/PlSqlKeyword.kt @@ -198,6 +198,8 @@ enum class PlSqlKeyword(override val value: String, val isReserved: Boolean = fa DEC("dec"), DECIMAL("decimal"), DEFAULTS("defaults"), + DEFERRABLE("deferrable"), + DEFERRED("deferred"), DEFINER("definer"), DELEGATE("delegate"), DELETE("delete"), @@ -273,6 +275,7 @@ enum class PlSqlKeyword(override val value: String, val isReserved: Boolean = fa INDICATOR("indicator"), INDICES("indices"), INITIAL("initial"), + INITIALLY("initially"), INITRANS("initrans"), INLINE("inline"), INNER("inner"), @@ -368,6 +371,8 @@ enum class PlSqlKeyword(override val value: String, val isReserved: Boolean = fa NONE("none"), NONEDITIONABLE("noneditionable"), NOORDER("noorder"), + NOPRECHECK("noprecheck"), + NORELY("norely"), NOSCHEMACHECK("noschemacheck"), NOTFOUND("notfound"), NOVALIDATE("novalidate"), @@ -414,6 +419,7 @@ enum class PlSqlKeyword(override val value: String, val isReserved: Boolean = fa PRAGMA("pragma"), PRECEDES("precedes"), PRECEDING("preceding"), + PRECHECK("precheck"), PRECISION("precision"), PREPEND("prepend"), PRESERVE("preserve"), @@ -435,6 +441,7 @@ enum class PlSqlKeyword(override val value: String, val isReserved: Boolean = fa REFRESH("refresh"), REJECT("reject"), RELIES_ON("relies_on"), + RELY("rely"), REMOVE("remove"), RENAME("rename"), REPEAT("repeat"), @@ -468,12 +475,12 @@ enum class PlSqlKeyword(override val value: String, val isReserved: Boolean = fa SECOND("second"), SEGMENT("segment"), SELF("self"), - SET("set"), SEQUENCE("sequence"), SERIALIZABLE("serializable"), SERIALLY_REUSABLE("serially_reusable"), SERVERERROR("servererror"), SESSION("session"), + SET("set"), SETS("sets"), SETTINGS("settings"), SHARING("sharing"), diff --git a/zpa-core/src/test/kotlin/org/sonar/plugins/plsqlopen/api/ddl/InlineConstraintTest.kt b/zpa-core/src/test/kotlin/org/sonar/plugins/plsqlopen/api/ddl/InlineConstraintTest.kt index 92aeff60..1ec32fc8 100644 --- a/zpa-core/src/test/kotlin/org/sonar/plugins/plsqlopen/api/ddl/InlineConstraintTest.kt +++ b/zpa-core/src/test/kotlin/org/sonar/plugins/plsqlopen/api/ddl/InlineConstraintTest.kt @@ -80,6 +80,8 @@ class InlineConstraintTest : RuleTest() { @Test fun matchesCheck() { assertThat(p).matches("check (x > 1)") + assertThat(p).matches("check (x > 1) disable precheck") + assertThat(p).matches("check (x > 1) precheck") } @Test @@ -87,4 +89,24 @@ class InlineConstraintTest : RuleTest() { assertThat(p).matches("constraint pk primary key") } + @Test + fun matchesUniqueWithMultipleStates() { + assertThat(p).matches("unique initially deferred") + assertThat(p).matches("unique initially immediate") + assertThat(p).matches("unique initially deferred deferrable") + assertThat(p).matches("unique initially deferred not deferrable") + assertThat(p).matches("unique deferrable") + assertThat(p).matches("unique not deferrable") + assertThat(p).matches("unique deferrable initially deferred") + assertThat(p).matches("unique not deferrable initially deferred") + assertThat(p).matches("unique rely") + assertThat(p).matches("unique norely") + assertThat(p).matches("unique enable") + assertThat(p).matches("unique disable") + assertThat(p).matches("unique validate") + assertThat(p).matches("unique novalidate") + assertThat(p).matches("unique exceptions into sch.tab") + assertThat(p).matches("unique not deferrable initially deferred rely disable validate exceptions into sch.tab") + } + } diff --git a/zpa-core/src/test/kotlin/org/sonar/plugins/plsqlopen/api/ddl/OutOfLineConstraintTest.kt b/zpa-core/src/test/kotlin/org/sonar/plugins/plsqlopen/api/ddl/OutOfLineConstraintTest.kt index 81851538..a243090a 100644 --- a/zpa-core/src/test/kotlin/org/sonar/plugins/plsqlopen/api/ddl/OutOfLineConstraintTest.kt +++ b/zpa-core/src/test/kotlin/org/sonar/plugins/plsqlopen/api/ddl/OutOfLineConstraintTest.kt @@ -65,6 +65,8 @@ class OutOfLineConstraintTest : RuleTest() { @Test fun matchesCheck() { assertThat(p).matches("check (x > 1)") + assertThat(p).matches("check (x > 1) disable precheck") + assertThat(p).matches("check (x > 1) precheck") } @Test @@ -72,4 +74,25 @@ class OutOfLineConstraintTest : RuleTest() { assertThat(p).matches("constraint pk primary key (foo)") } + @Test + + fun matchesUniqueWithMultipleStates() { + assertThat(p).matches("unique (foo) initially deferred") + assertThat(p).matches("unique (foo) initially immediate") + assertThat(p).matches("unique (foo) initially deferred deferrable") + assertThat(p).matches("unique (foo) initially deferred not deferrable") + assertThat(p).matches("unique (foo) deferrable") + assertThat(p).matches("unique (foo) not deferrable") + assertThat(p).matches("unique (foo) deferrable initially deferred") + assertThat(p).matches("unique (foo) not deferrable initially deferred") + assertThat(p).matches("unique (foo) rely") + assertThat(p).matches("unique (foo) norely") + assertThat(p).matches("unique (foo) enable") + assertThat(p).matches("unique (foo) disable") + assertThat(p).matches("unique (foo) validate") + assertThat(p).matches("unique (foo) novalidate") + assertThat(p).matches("unique (foo) exceptions into sch.tab") + assertThat(p).matches("unique (foo) not deferrable initially deferred rely disable validate exceptions into sch.tab") + } + }