Repository: sqlfluff/sqlfluff
Pull request: L029: Optionally check quoted identifiers in addition to naked identifiers
Fixes #1747

This PR adjusts L029 to optionally check quoted identifiers in addition to naked identifiers.
In order to do this, we are adding a new configuration keyword, quoted_identifiers_policy, which represents the same thing as unquoted_identifiers_policy but for quoted identifiers.
The options for quoted_identifiers_policy are the same as unquoted_identifiers_policy with the addition of none, representing no checks for quoted identifiers.

We check quoted identifiers by stripping off the first and last character.  If we have a case where this shortcut would fail, we'll need to tweak the code before merging.

Changes:
+quoted_identifiers_policy default of none to default_config.cfg
+quoted_identifiers_policy description in config_info.py
L014.py: Rename unquoted_ids_policy_applicable function to identifiers_policy_applicable in order to reflect change in functionality
L029.py: Reflect renaming of unquoted_ids_policy_applicable function; add quoted_identifiers_policy as a configuration keyword; adjust rule to check quoted identifiers based on the config setting.
L029.yml: Rename test cases to be more descriptive.  Add quoted identifier test cases.


Problem statement:
New Rule Suggestion: Identify and flag object names that are reserved words
We should be able to identify and flag the creation of objects that share names with reserved words.

Anti-pattern:
```
CREATE TABLE DBO.ColumnNames2
(
    [Table] INT,
    [Select] INT,
    [Create] INT,
    [Drop] INT
)
```

Hints from issue discussion:

Commit message: L029: Check quoted identifiers in addition to naked identifiers

Patch to review:
diff --git a/src/sqlfluff/rules/L029.py b/src/sqlfluff/rules/L029.py
index cec9d5b1a64..9b51ba8100b 100644
--- a/src/sqlfluff/rules/L029.py
+++ b/src/sqlfluff/rules/L029.py
@@ -35,13 +35,28 @@ class Rule_L029(BaseRule):
     def _eval(self, context: RuleContext) -> Optional[LintResult]:
         """Keywords should not be used as identifiers."""
         if (
-            context.segment.name == "naked_identifier"
-            and unquoted_ids_policy_applicable(
-                self.unquoted_identifiers_policy, context.parent_stack  # type: ignore
+            (
+                context.segment.name == "naked_identifier"
+                and unquoted_ids_policy_applicable(
+                    self.unquoted_identifiers_policy, context.parent_stack  # type: ignore
+                )
+                and (
+                    context.segment.raw.upper()
+                    in context.dialect.sets("unreserved_keywords")
+                )
             )
-            and (
-                context.segment.raw.upper()
-                in context.dialect.sets("unreserved_keywords")
+        ) or (
+            (
+                context.segment.name == "quoted_identifier"
+                and unquoted_ids_policy_applicable(
+                    self.unquoted_identifiers_policy, context.parent_stack  # type: ignore
+                )
+                and (
+                    context.segment.raw.upper()[1:-1]
+                    in context.dialect.sets("unreserved_keywords")
+                    or context.segment.raw.upper()[1:-1]
+                    in context.dialect.sets("reserved_keywords")
+                )
             )
         ):
             return LintResult(anchor=context.segment)
diff --git a/test/fixtures/rules/std_rule_cases/L029.yml b/test/fixtures/rules/std_rule_cases/L029.yml
index 44d4593ca18..82ccbb21467 100644
--- a/test/fixtures/rules/std_rule_cases/L029.yml
+++ b/test/fixtures/rules/std_rule_cases/L029.yml
@@ -36,3 +36,11 @@ test_fail_keyword_as_identifier_5:
     rules:
       L029:
         unquoted_identifiers_policy: column_aliases
+
+test_fail_keyword_as_quoted_identifier:
+  fail_str: SELECT x AS [date] FROM tbl AS parameter
+  configs:
+    rules:
+      L029:
+        unquoted_identifiers_policy: column_aliases
+      dialect: tsql


Code review comments:
diff_hunk: @@ -36,3 +36,11 @@ test_fail_keyword_as_identifier_5:
     rules:
       L029:
         unquoted_identifiers_policy: column_aliases
+
+test_fail_keyword_as_quoted_identifier:
+  fail_str: SELECT x AS [date] FROM tbl AS parameter
+  configs:
+    rules:
+      L029:
+        unquoted_identifiers_policy: column_aliases
+      dialect: tsql
path: test/fixtures/rules/std_rule_cases/L029.yml
text: @user1:
This setting is not correct. Dialect belongs under a `core:` section, e.g.
```
  configs:
    core:
      dialect: exasol
```

See L003.yml, for example.