Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

References rule bundle #4446

Merged
merged 5 commits into from
Mar 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 6 additions & 6 deletions docs/source/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -241,21 +241,21 @@ active for a given file.


For example, to disable the rules :class:`L022 <sqlfluff.core.rules.Rule_L022>`
and :class:`L027 <sqlfluff.core.rules.Rule_L027>`:
and :class:`RF02 <sqlfluff.core.rules.Rule_RF02>`:

.. code-block:: cfg

[sqlfluff]
exclude_rules = L022, L027
exclude_rules = L022, RF02

To enable individual rules, configure :code:`rules`, respectively.

For example, to enable :class:`L027 <sqlfluff.core.rules.Rule_L027>`:
For example, to enable :class:`RF02 <sqlfluff.core.rules.Rule_RF02>`:

.. code-block:: cfg

[sqlfluff]
rules = L027
rules = RF02

Rules can also be enabled/disabled by their grouping. Right now, the only
rule grouping is :code:`core`. This will enable (or disable) a select group
Expand Down Expand Up @@ -892,7 +892,7 @@ You already know you can pass arguments (:code:`--verbose`,

.. code-block:: text

$ sqlfluff lint my_code.sql -v --exclude-rules L022,L027
$ sqlfluff lint my_code.sql -v --exclude-rules L022,RF02

You might have arguments that you pass through every time, e.g rules you
*always* want to ignore. These can also be configured:
Expand All @@ -901,7 +901,7 @@ You might have arguments that you pass through every time, e.g rules you

[sqlfluff]
verbose = 1
exclude_rules = L022,L027
exclude_rules = L022,RF02

Note that while the :code:`exclude_rules` config looks similar to the
above example, the :code:`verbose` config has an integer value. This is
Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ sqlfluff =
# to a templater plugin.
sqlfluff_rules_capitalisation = sqlfluff.rules.capitalisation
sqlfluff_rules_aliasing = sqlfluff.rules.aliasing
sqlfluff_rules_references = sqlfluff.rules.references
sqlfluff_rules_ambiguous = sqlfluff.rules.ambiguous
sqlfluff_rules_structure = sqlfluff.rules.structure
sqlfluff_rules_jinja = sqlfluff.rules.jinja
Expand Down
12 changes: 6 additions & 6 deletions src/sqlfluff/core/default_config.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -224,22 +224,22 @@ aliasing = explicit
ignore_comment_lines = False
ignore_comment_clauses = False

[sqlfluff:rules:L027]
[sqlfluff:rules:RF02]
# Comma separated list of words to ignore for this rule
ignore_words = None
ignore_words_regex = None

[sqlfluff:rules:L026]
[sqlfluff:rules:RF01]
# References must be in FROM clause
# Disabled for some dialects (e.g. bigquery)
force_enable = False

[sqlfluff:rules:L028]
[sqlfluff:rules:RF03]
# References must be consistently used
# Disabled for some dialects (e.g. bigquery)
force_enable = False

[sqlfluff:rules:L029]
[sqlfluff:rules:RF04]
# Keywords should not be used as identifiers.
unquoted_identifiers_policy = aliases
quoted_identifiers_policy = none
Expand Down Expand Up @@ -281,7 +281,7 @@ require_final_semicolon = False
# GROUP BY/ORDER BY column references
group_by_and_order_by_style = consistent

[sqlfluff:rules:L057]
[sqlfluff:rules:RF05]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any plans to allow using the new "readable" rule names in the config rather than the codes?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll slack you about this. Short answer - not at the moment because if we accept more than one way of specifying config, we then have to deal with resolving priority.

# Special characters in identifiers
unquoted_identifiers_policy = all
quoted_identifiers_policy = all
Expand All @@ -290,7 +290,7 @@ additional_allowed_characters = None
ignore_words = None
ignore_words_regex = None

[sqlfluff:rules:L059]
[sqlfluff:rules:RF06]
# Policy on quoted and unquoted identifiers
prefer_quoted_identifiers = False
ignore_words = None
Expand Down
23 changes: 2 additions & 21 deletions src/sqlfluff/rules/capitalisation/CP02.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,13 @@
"""Implementation of Rule CP02."""

from typing import Tuple, Optional, List
from typing import Optional, List

from sqlfluff.core.parser import BaseSegment
from sqlfluff.core.rules import LintResult, RuleContext
from sqlfluff.core.rules.crawlers import SegmentSeekerCrawler
from sqlfluff.utils.identifers import identifiers_policy_applicable
from sqlfluff.rules.capitalisation.CP01 import Rule_CP01


def identifiers_policy_applicable(
policy: str, parent_stack: Tuple[BaseSegment, ...]
) -> bool:
"""Does `(un)quoted_identifiers_policy` apply to this segment?"""
if policy == "all":
return True
if policy == "none":
return False
is_alias = parent_stack and parent_stack[-1].is_type(
"alias_expression", "column_definition", "with_compound_statement"
)
if policy == "aliases" and is_alias:
return True
is_inside_from = any(p.is_type("from_clause") for p in parent_stack)
if policy == "column_aliases" and is_alias and not is_inside_from:
return True
return False


class Rule_CP02(Rule_CP01):
"""Inconsistent capitalisation of unquoted identifiers.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Implementation of Rule L026."""
"""Implementation of Rule RF01."""
from dataclasses import dataclass, field
from typing import cast, List, Optional, Tuple

Expand Down Expand Up @@ -28,14 +28,14 @@


@dataclass
class L026Query(SelectCrawlerQuery):
"""SelectCrawler Query with custom L026 info."""
class RF01Query(SelectCrawlerQuery):
"""SelectCrawler Query with custom RF01 info."""

aliases: List[AliasInfo] = field(default_factory=list)
standalone_aliases: List[str] = field(default_factory=list)


class Rule_L026(BaseRule):
class Rule_RF01(BaseRule):
"""References cannot reference objects not present in ``FROM`` clause.

.. note::
Expand Down Expand Up @@ -67,7 +67,9 @@ class Rule_L026(BaseRule):

"""

groups = ("all", "core")
name = "references.from"
aliases = ("L026",)
groups = ("all", "core", "references")
config_keywords = ["force_enable"]
crawl_behaviour = SegmentSeekerCrawler(set(_START_TYPES))
_dialects_disabled_by_default = [
Expand Down Expand Up @@ -106,9 +108,9 @@ def _eval(self, context: RuleContext) -> EvalResultType:
# Verify table references in any SELECT statements found in or
# below context.segment in the parser tree.
crawler = SelectCrawler(
context.segment, context.dialect, query_class=L026Query
context.segment, context.dialect, query_class=RF01Query
)
query: L026Query = cast(L026Query, crawler.query_tree)
query: RF01Query = cast(RF01Query, crawler.query_tree)
if query:
self._analyze_table_references(
query, dml_target_table, context.dialect, violations
Expand All @@ -130,7 +132,7 @@ def _table_ref_as_tuple(table_reference) -> Tuple[str, ...]:

def _analyze_table_references(
self,
query: L026Query,
query: RF01Query,
dml_target_table: Optional[Tuple[str, ...]],
dialect: Dialect,
violations: List[LintResult],
Expand Down Expand Up @@ -166,7 +168,7 @@ def _analyze_table_references(
# Visit children.
for child in query.children:
self._analyze_table_references(
cast(L026Query, child), dml_target_table, dialect, violations
cast(RF01Query, child), dml_target_table, dialect, violations
)

@staticmethod
Expand Down Expand Up @@ -213,7 +215,7 @@ def _get_table_refs(ref, dialect):
return tbl_refs

def _resolve_reference(
self, r, tbl_refs, dml_target_table: Optional[Tuple[str, ...]], query: L026Query
self, r, tbl_refs, dml_target_table: Optional[Tuple[str, ...]], query: RF01Query
):
# Does this query define the referenced table?
possible_references = [tbl_ref[1] for tbl_ref in tbl_refs]
Expand All @@ -226,7 +228,7 @@ def _resolve_reference(
# No. Check the parent query, if there is one.
if query.parent:
return self._resolve_reference(
r, tbl_refs, dml_target_table, cast(L026Query, query.parent)
r, tbl_refs, dml_target_table, cast(RF01Query, query.parent)
)
# No parent query. If there's a DML statement at the root, check its
# target table or alias.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"""Implementation of Rule L027."""
"""Implementation of Rule RF02."""
import regex
from typing import List, Optional

from sqlfluff.core.rules import LintResult
from sqlfluff.rules.aliasing.AL04 import Rule_AL04


class Rule_L027(Rule_AL04):
class Rule_RF02(Rule_AL04):
"""References should be qualified if select has more than one referenced table/view.

.. note::
Expand Down Expand Up @@ -34,7 +34,9 @@ class Rule_L027(Rule_AL04):
LEFT JOIN vee ON vee.a = foo.a
"""

groups = ("all",)
name = "references.qualification"
aliases = ("L027",)
groups = ("all", "references")
# Crawl behaviour is defined in AL04

def _lint_references_and_aliases(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Implementation of Rule L028."""
"""Implementation of Rule RF03."""

from typing import Iterator, List, Optional, Set

Expand All @@ -22,7 +22,7 @@
_START_TYPES = ["select_statement", "set_expression", "with_compound_statement"]


class Rule_L028(BaseRule):
class Rule_RF03(BaseRule):
"""References should be consistent in statements with a single table.

.. note::
Expand Down Expand Up @@ -64,7 +64,9 @@ class Rule_L028(BaseRule):

"""

groups = ("all",)
name = "references.consistent"
aliases = ("L028",)
groups = ("all", "references")
config_keywords = [
"single_table_references",
"force_enable",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
"""Implementation of Rule L029."""
"""Implementation of Rule RF04."""
import regex
from typing import Optional

from sqlfluff.core.rules import BaseRule, LintResult, RuleContext
from sqlfluff.core.rules.crawlers import SegmentSeekerCrawler
from sqlfluff.utils.identifers import identifiers_policy_applicable

from sqlfluff.rules.capitalisation.CP02 import identifiers_policy_applicable


class Rule_L029(BaseRule):
class Rule_RF04(BaseRule):
"""Keywords should not be used as identifiers.

Although `unreserved` keywords `can` be used as identifiers,
Expand Down Expand Up @@ -42,7 +41,9 @@ class Rule_L029(BaseRule):

"""

groups = ("all",)
name = "references.keywords"
aliases = ("L029",)
groups = ("all", "references")
crawl_behaviour = SegmentSeekerCrawler({"naked_identifier", "quoted_identifier"})
config_keywords = [
"unquoted_identifiers_policy",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
"""Implementation of Rule L057."""
"""Implementation of Rule RF05."""
from typing import Optional, Set, List

import regex

from sqlfluff.core.rules import BaseRule, LintResult, RuleContext
from sqlfluff.core.rules.crawlers import SegmentSeekerCrawler
from sqlfluff.rules.capitalisation.CP02 import identifiers_policy_applicable
from sqlfluff.utils.identifers import identifiers_policy_applicable


class Rule_L057(BaseRule):
class Rule_RF05(BaseRule):
"""Do not use special characters in identifiers.

**Anti-pattern**
Expand Down Expand Up @@ -41,7 +41,9 @@ class Rule_L057(BaseRule):

"""

groups = ("all",)
name = "references.special_chars"
aliases = ("L057",)
groups = ("all", "references")
config_keywords = [
"quoted_identifiers_policy",
"unquoted_identifiers_policy",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Implementation of Rule L059."""
"""Implementation of Rule RF06."""

from typing import List, Optional, cast, Type

Expand All @@ -10,7 +10,7 @@
from sqlfluff.utils.functional import sp, FunctionalContext


class Rule_L059(BaseRule):
class Rule_RF06(BaseRule):
"""Unnecessary quoted identifier.

This rule will fail if the quotes used to quote an identifier are (un)necessary
Expand Down Expand Up @@ -72,7 +72,9 @@ class Rule_L059(BaseRule):

"""

groups = ("all",)
name = "references.quoting"
aliases = ("L059",)
groups = ("all", "references")
config_keywords = [
"prefer_quoted_identifiers",
"ignore_words",
Expand Down
16 changes: 16 additions & 0 deletions src/sqlfluff/rules/references/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""The references plugin bundle."""

from sqlfluff.core.plugin import hookimpl

from sqlfluff.rules.references.RF01 import Rule_RF01
from sqlfluff.rules.references.RF02 import Rule_RF02
from sqlfluff.rules.references.RF03 import Rule_RF03
from sqlfluff.rules.references.RF04 import Rule_RF04
from sqlfluff.rules.references.RF05 import Rule_RF05
from sqlfluff.rules.references.RF06 import Rule_RF06


@hookimpl
def get_rules():
"""Get plugin rules."""
return [Rule_RF01, Rule_RF02, Rule_RF03, Rule_RF04, Rule_RF05, Rule_RF06]