Repository: sqlfluff/sqlfluff

Issue:
L026 error while using bigquery nested field
Consider the following sql:

```sql
WITH commit_info AS (
    SELECT
        commit,
        author.name AS author_name
    FROM `bigquery-public-data.github_repos.commits`
    LIMIT 10
)

SELECT * FROM commit_info
```

## Expected Behaviour
Lint should not fail with L026 error

## Observed Behaviour
Lint fails with following error:
```
L:   4 | P:   9 | L026 | Reference 'author.name' refers to table/view not found
                       | in the FROM clause or found in parent subquery.
```

## Dialect
bigquery

## Version
- sqlfluff, version 0.6.6
- Python 3.9.7



Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/sqlfluff/sqlfluff/pull/1504?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sqlfluff) Report
> Merging [#1504](https://codecov.io/gh/sqlfluff/sqlfluff/pull/1504?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sqlfluff) (0f85ac7) into [main](https://codecov.io/gh/sqlfluff/sqlfluff/commit/7e701137ea20d7863952baa5b451fc47ec508bd0?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sqlfluff) (7e70113) will **not change** coverage.
> The diff coverage is `100.00%`.

> :exclamation: Current head 0f85ac7 differs from pull request most recent head 845afff. Consider uploading reports for the commit 845afff to get more accurate results
[![Impacted file tree graph](https://codecov.io/gh/sqlfluff/sqlfluff/pull/1504/graphs/tree.svg?width=650&height=150&src=pr&token=maM8kLgCmn&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sqlfluff)](https://codecov.io/gh/sqlfluff/sqlfluff/pull/1504?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sqlfluff)

```diff
@@            Coverage Diff            @@
##              main     #1504   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          130       130           
  Lines         9063      9074   +11     
=========================================
+ Hits          9063      9074   +11     
```


| [Impacted Files](https://codecov.io/gh/sqlfluff/sqlfluff/pull/1504?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sqlfluff) | Coverage Δ | |
|---|---|---|
| [src/sqlfluff/core/rules/config\_info.py](https://codecov.io/gh/sqlfluff/sqlfluff/pull/1504/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sqlfluff#diff-c3JjL3NxbGZsdWZmL2NvcmUvcnVsZXMvY29uZmlnX2luZm8ucHk=) | `100.00% <ø> (ø)` | |
| [src/sqlfluff/dialects/dialect\_ansi.py](https://codecov.io/gh/sqlfluff/sqlfluff/pull/1504/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sqlfluff#diff-c3JjL3NxbGZsdWZmL2RpYWxlY3RzL2RpYWxlY3RfYW5zaS5weQ==) | `100.00% <ø> (ø)` | |
| [src/sqlfluff/dialects/dialect\_postgres.py](https://codecov.io/gh/sqlfluff/sqlfluff/pull/1504/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sqlfluff#diff-c3JjL3NxbGZsdWZmL2RpYWxlY3RzL2RpYWxlY3RfcG9zdGdyZXMucHk=) | `100.00% <ø> (ø)` | |
| [src/sqlfluff/rules/L026.py](https://codecov.io/gh/sqlfluff/sqlfluff/pull/1504/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sqlfluff#diff-c3JjL3NxbGZsdWZmL3J1bGVzL0wwMjYucHk=) | `100.00% <100.00%> (ø)` | |
| [src/sqlfluff/rules/L028.py](https://codecov.io/gh/sqlfluff/sqlfluff/pull/1504/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sqlfluff#diff-c3JjL3NxbGZsdWZmL3J1bGVzL0wwMjgucHk=) | `100.00% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/sqlfluff/sqlfluff/pull/1504?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sqlfluff).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sqlfluff)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/sqlfluff/sqlfluff/pull/1504?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sqlfluff). Last update [56b2dd8...845afff](https://codecov.io/gh/sqlfluff/sqlfluff/pull/1504?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sqlfluff). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sqlfluff).

tunetheweb: Addressed the simple issues and answered the more complex ones but don't think we should address now. Could you have another look @barrywhart ?

Patch:
diff --git a/src/sqlfluff/core/default_config.cfg b/src/sqlfluff/core/default_config.cfg
index e85fde9da..75c19a9b5 100644
--- a/src/sqlfluff/core/default_config.cfg
+++ b/src/sqlfluff/core/default_config.cfg
@@ -66,6 +66,12 @@ extended_capitalisation_policy = consistent
 [sqlfluff:rules:L016]
 ignore_comment_lines = False
 
+[sqlfluff:rules:L026]
+force_enable = False
+
+[sqlfluff:rules:L028]
+force_enable = False
+
 [sqlfluff:rules:L029]  # Keyword identifiers
 unquoted_identifiers_policy = aliases
 
diff --git a/src/sqlfluff/core/rules/config_info.py b/src/sqlfluff/core/rules/config_info.py
index fc7bc65d9..673a142cf 100644
--- a/src/sqlfluff/core/rules/config_info.py
+++ b/src/sqlfluff/core/rules/config_info.py
@@ -42,6 +42,12 @@ STANDARD_CONFIG_INFO_DICT = {
         "validation": ["consistent", "qualified", "unqualified"],
         "definition": "The expectation for references in single-table select",
     },
+    "force_enable": {
+        "validation": [True, False],
+        "definition": (
+            "Run this rule even for dialects where this rule is disabled by default"
+        ),
+    },
     "unquoted_identifiers_policy": {
         "validation": ["all", "aliases", "column_aliases"],
         "definition": "Types of unquoted identifiers to flag violations for",
diff --git a/src/sqlfluff/rules/L026.py b/src/sqlfluff/rules/L026.py
index ff175fda7..cade3e5b7 100644
--- a/src/sqlfluff/rules/L026.py
+++ b/src/sqlfluff/rules/L026.py
@@ -2,12 +2,18 @@
 
 from sqlfluff.core.rules.analysis.select import get_aliases_from_select
 from sqlfluff.core.rules.base import LintResult
+from sqlfluff.core.rules.doc_decorators import document_configuration
 from sqlfluff.rules.L025 import Rule_L020
 
 
+@document_configuration
 class Rule_L026(Rule_L020):
     """References cannot reference objects not present in FROM clause.
 
+    NB: This rule is disabled by default for BigQuery due to its use of
+    structs which trigger false positives. It can be enabled with the
+    `force_enable = True` flag.
+
     | **Anti-pattern**
     | In this example, the reference 'vee' has not been declared.
 
@@ -28,6 +34,8 @@ class Rule_L026(Rule_L020):
 
     """
 
+    config_keywords = ["force_enable"]
+
     @staticmethod
     def _is_bad_tbl_ref(table_aliases, parent_select, tbl_ref):
         """Given a table reference, try to find what it's referring to."""
@@ -76,3 +84,14 @@ class Rule_L026(Rule_L020):
                     )
                 )
         return violation_buff or None
+
+    def _eval(self, segment, parent_stack, dialect, **kwargs):
+        """Override Rule L020 for dialects that use structs.
+
+        Some dialects use structs (e.g. column.field) which look like
+        table references and so incorrectly trigger this rule.
+        """
+        if dialect.name in ["bigquery"] and not self.force_enable:
+            return LintResult()
+
+        return super()._eval(segment, parent_stack, dialect, **kwargs)
diff --git a/src/sqlfluff/rules/L028.py b/src/sqlfluff/rules/L028.py
index ff2cade32..52f37a886 100644
--- a/src/sqlfluff/rules/L028.py
+++ b/src/sqlfluff/rules/L028.py
@@ -9,6 +9,10 @@ from sqlfluff.rules.L025 import Rule_L025
 class Rule_L028(Rule_L025):
     """References should be consistent in statements with a single table.
 
+    NB: This rule is disabled by default for BigQuery due to its use of
+    structs which trigger false positives. It can be enabled with the
+    `force_enable = True` flag.
+
     | **Anti-pattern**
     | In this example, only the field `b` is referenced.
 
@@ -38,7 +42,7 @@ class Rule_L028(Rule_L025):
 
     """
 
-    config_keywords = ["single_table_references"]
+    config_keywords = ["single_table_references", "force_enable"]
 
     def _lint_references_and_aliases(
         self,
@@ -92,3 +96,14 @@ class Rule_L028(Rule_L025):
             seen_ref_types.add(this_ref_type)
 
         return violation_buff or None
+
+    def _eval(self, segment, parent_stack, dialect, **kwargs):
+        """Override Rule L025 for dialects that use structs.
+
+        Some dialects use structs (e.g. column.field) which look like
+        table references and so incorrectly trigger this rule.
+        """
+        if dialect.name in ["bigquery"] and not self.force_enable:
+            return LintResult()
+
+        return super()._eval(segment, parent_stack, dialect, **kwargs)
diff --git a/src/sqlfluff/rules/L033.py b/src/sqlfluff/rules/L033.py
index b6ebaf958..e6ea0aadc 100644
--- a/src/sqlfluff/rules/L033.py
+++ b/src/sqlfluff/rules/L033.py
@@ -8,6 +8,9 @@ from sqlfluff.core.rules.base import BaseRule, LintFix, LintResult
 class Rule_L033(BaseRule):
     """UNION [DISTINCT|ALL] is preferred over just UNION.
 
+    NB: This rule is only enabled for dialects that support UNION DISTINCT
+    (`ansi`, `bigquery`, `hive`, and `mysql`).
+
     | **Anti-pattern**
     | In this example, UNION DISTINCT should be preferred over UNION, because
     | explicit is better than implicit.


Test patch:
diff --git a/test/fixtures/rules/std_rule_cases/L026.yml b/test/fixtures/rules/std_rule_cases/L026.yml
index 2d84ccaaa..81283fd59 100644
--- a/test/fixtures/rules/std_rule_cases/L026.yml
+++ b/test/fixtures/rules/std_rule_cases/L026.yml
@@ -7,6 +7,9 @@ test_pass_object_referenced_1:
   configs:
     core:
       dialect: bigquery
+    rules:
+      L026:
+        force_enable: True
 
 test_fail_object_not_referenced_1:
   desc: Name foo is not referenced in FROM clause. It would need to be at the end of identifier in ticks or an alias.
@@ -15,6 +18,9 @@ test_fail_object_not_referenced_1:
   configs:
     core:
       dialect: bigquery
+    rules:
+      L026:
+        force_enable: True
 
 test_fail_object_not_referenced_2:
   # References in WHERE clause
@@ -39,4 +45,38 @@ test_pass_object_referenced_4:
     FROM `example_dataset2.example_table2` AS et2
   configs:
     core:
-      dialect: bigquery
\ No newline at end of file
+      dialect: bigquery
+    rules:
+      L026:
+        force_enable: True
+
+test_pass_object_referenced_5a:
+  # Test ambiguous column reference caused by use of BigQuery structure fields.
+  # Here, column,field should not trigger the rule as by default this rule is
+  # disabled for bigquery
+  # https://github.com/sqlfluff/sqlfluff/issues/1503
+  pass_str: |
+    SELECT column.field
+    FROM `example_dataset2.example_table2`
+  configs:
+    core:
+      dialect: bigquery
+
+test_pass_object_referenced_5b:
+  # Same test as above but default (ANSI) should trigger
+  fail_str: |
+    SELECT column.field
+    FROM table1
+
+test_pass_object_referenced_5c:
+  # Same test as above but for BigQuery but force is
+  # enabled so should fail
+  fail_str: |
+    SELECT column.field
+    FROM `example_dataset2.example_table2`
+  configs:
+    core:
+      dialect: bigquery
+    rules:
+      L026:
+        force_enable: True
diff --git a/test/fixtures/rules/std_rule_cases/L028.yml b/test/fixtures/rules/std_rule_cases/L028.yml
index 0d7b28c38..6df119e12 100644
--- a/test/fixtures/rules/std_rule_cases/L028.yml
+++ b/test/fixtures/rules/std_rule_cases/L028.yml
@@ -44,3 +44,28 @@ test_value_table_functions_do_not_require_qualification:
   configs:
     core:
       dialect: bigquery
+    rules:
+      L028:
+        force_enable: True
+
+test_object_references_1a:
+  # This should fail as "a" is an unreference object
+  fail_str: SELECT a.bar, b FROM my_tbl
+
+test_object_references_1b:
+  # This should not-fail as "a" is potentially a STRUCT
+  pass_str: SELECT a.bar, b FROM my_tbl
+  configs:
+    core:
+      dialect: bigquery
+
+test_object_references_1c:
+  # This should fail as even though "a" is potenitally a STRUCT
+  # The config has been set to enforce the rule
+  fail_str: SELECT a.bar, b FROM my_tbl
+  configs:
+    core:
+      dialect: bigquery
+    rules:
+      L028:
+        force_enable: True