Skip to content

Commit

Permalink
fix/issue 105/support additional operators (#112)
Browse files Browse the repository at this point in the history
* fix: add support for more operators, closes #105

* refactor: clean up node and comment imports

* fix: add support for snowflake's minus keyword

* fix: add grouping operators
  • Loading branch information
tconbeer authored Feb 2, 2022
1 parent 2cc8825 commit e2e9286
Show file tree
Hide file tree
Showing 13 changed files with 121 additions and 21 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file.
### Fixes

- adds "cross join" to list of supported join types. No longer merges the "cross" keyword with the previous statement ([#110](https://github.com/tconbeer/sqlfmt/issues/110) - thank you [@rdeese](https://github.com/rdeese)!)
- add support for every valid operator in postgresql, even the weird ones, like `@>`, `||/`, `?-|` ([#105](https://github.com/tconbeer/sqlfmt/issues/105))

## [0.4.3] - 2022-01-31

Expand Down
4 changes: 3 additions & 1 deletion src/sqlfmt/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
from typing import List, Optional

from sqlfmt.analyzer import MAYBE_WHITESPACES, Analyzer, group
from sqlfmt.comment import Comment
from sqlfmt.exception import SqlfmtBracketError, StopJinjaLexing
from sqlfmt.line import Comment, Line, Node
from sqlfmt.line import Line
from sqlfmt.node import Node
from sqlfmt.token import Token, TokenType


Expand Down
4 changes: 3 additions & 1 deletion src/sqlfmt/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
from dataclasses import dataclass, field
from typing import Callable, Dict, List, Optional

from sqlfmt.comment import Comment
from sqlfmt.exception import SqlfmtBracketError, SqlfmtParsingError
from sqlfmt.line import Comment, Line, Node
from sqlfmt.line import Line
from sqlfmt.node import Node
from sqlfmt.query import Query


Expand Down
43 changes: 36 additions & 7 deletions src/sqlfmt/dialect.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,12 +220,33 @@ def __init__(self) -> None:
name="operator",
priority=910,
pattern=group(
r"\|\|?\/", # square or cube root ||/
r"~=", # geo compare
r"!?~\*?", # posix like/not like
r"\?(=|!|<=|<!)", # regex lookahead/behind
r"\?(-\||\|\||-|\|)", # regex lookahead/behind
r"@-@", # length operator
r"@@@?", # center point operator; also text match
r"##", # closest point
r"<->", # distance operator
r"@>", # contains
r"<@", # contained by
r"<>",
r"!=",
r"\|?>>=?",
r"<<(=|\|)?",
r"=>",
r"(-|#)>>?", # json extraction
r"&&",
r"&<\|?", # not extends
r"\|?&>", # not extends
r"<\^", # below
r">\^", # above
r"\?#", # intersect
r"\|\|",
r"[+\-*/%&@|^=<>:]=?",
r"~",
r"-\|-",
r"[*+?]?\?", # regex greedy/non-greedy, also ?
r"!!", # negate text match
r"[+\-*/%&|^=<>:#!]=?", # singles
),
action=partial(
actions.add_node_to_buffer, token_type=TokenType.OPERATOR
Expand All @@ -235,16 +256,24 @@ def __init__(self) -> None:
name="word_operator",
priority=920,
pattern=group(
r"all",
r"any",
r"between",
r"cube",
r"exists",
r"grouping sets",
r"ilike",
r"in",
r"is",
r"isnull",
r"like",
r"not",
r"like(\s+any)?",
r"notnull",
r"not",
r"over",
r"similar",
r"rollup",
r"rlike",
r"some",
r"similar\s+to",
)
+ group(r"\W", r"$"),
action=partial(
Expand Down Expand Up @@ -311,7 +340,7 @@ def __init__(self) -> None:
r"having",
r"qualify",
r"window",
r"(union|intersect|except)(\s+all|distinct)?",
r"(union|intersect|except|minus)(\s+all|distinct)?",
r"order\s+by",
r"limit",
r"offset",
Expand Down
3 changes: 2 additions & 1 deletion src/sqlfmt/formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
from typing import List, Optional

from sqlfmt.jinjafmt import JinjaFormatter
from sqlfmt.line import Line, Node
from sqlfmt.line import Line
from sqlfmt.merger import LineMerger
from sqlfmt.mode import Mode
from sqlfmt.node import Node
from sqlfmt.query import Query
from sqlfmt.splitter import LineSplitter

Expand Down
3 changes: 2 additions & 1 deletion src/sqlfmt/jinjafmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
from types import ModuleType
from typing import Optional

from sqlfmt.line import Line, Node
from sqlfmt.line import Line
from sqlfmt.mode import Mode
from sqlfmt.node import Node


class BlackWrapper:
Expand Down
4 changes: 3 additions & 1 deletion src/sqlfmt/merger.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from dataclasses import dataclass
from typing import List

from sqlfmt.comment import Comment
from sqlfmt.exception import CannotMergeException
from sqlfmt.line import Comment, Line, Node
from sqlfmt.line import Line
from sqlfmt.mode import Mode
from sqlfmt.node import Node
from sqlfmt.token import TokenType


Expand Down
3 changes: 2 additions & 1 deletion src/sqlfmt/query.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from dataclasses import dataclass, field
from typing import List

from sqlfmt.line import Line, Node
from sqlfmt.line import Line
from sqlfmt.node import Node
from sqlfmt.token import Token


Expand Down
4 changes: 1 addition & 3 deletions tests/data/errors/900_bad_token.sql
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
select ?
from my_table
where no_question_mark is true
select $
4 changes: 2 additions & 2 deletions tests/unit_tests/test_analyzer.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import pytest

from sqlfmt.analyzer import Analyzer, SqlfmtParsingError
from sqlfmt.comment import Comment
from sqlfmt.exception import SqlfmtBracketError
from sqlfmt.line import Comment
from sqlfmt.mode import Mode
from sqlfmt.token import Token, TokenType
from tests.util import read_test_data
Expand Down Expand Up @@ -88,7 +88,7 @@ def test_simple_query_parsing(all_output_modes: Mode) -> None:


def test_parsing_error(default_analyzer: Analyzer) -> None:
source_string = "select !"
source_string = "select $"
with pytest.raises(SqlfmtParsingError):
_ = default_analyzer.parse_query(source_string=source_string)

Expand Down
2 changes: 0 additions & 2 deletions tests/unit_tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import pytest

from sqlfmt.analyzer import SqlfmtParsingError
from sqlfmt.api import (
_format_many,
_generate_matched_paths,
Expand Down Expand Up @@ -51,7 +50,6 @@ def test_format_empty_string(all_output_modes: Mode) -> None:
@pytest.mark.parametrize(
"source,exception",
[
("?\n", SqlfmtParsingError),
("select )\n", SqlfmtBracketError),
("{{\n", SqlfmtBracketError),
],
Expand Down
64 changes: 64 additions & 0 deletions tests/unit_tests/test_dialect.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,70 @@ def test_rule_props_are_unique(self, polyglot: Polyglot) -> None:
("main", "double_colon", "::"),
("main", "colon", ":"),
("main", "semicolon", ";"),
("main", "operator", "+"),
("main", "operator", "-"),
("main", "operator", "/"),
("main", "operator", "<>"),
("main", "operator", "||"),
("main", "operator", "=>"),
("main", "operator", "||/"),
("main", "operator", "|/"),
("main", "operator", "#"),
("main", "operator", ">>"),
("main", "operator", "<<"),
("main", "operator", "!"),
("main", "operator", "!="),
# posix like/ not like
("main", "operator", "~"),
("main", "operator", "!~"),
("main", "operator", "~*"),
("main", "operator", "!~*"),
# postgresql geo operators
# see: https://www.postgresql.org/docs/current/functions-geometry.html
("main", "operator", "@-@"),
("main", "operator", "@@"),
("main", "operator", "##"),
("main", "operator", "<->"),
("main", "operator", "<@"),
("main", "operator", "@>"),
("main", "operator", "&&"),
("main", "operator", "&<"),
("main", "operator", "&>"),
("main", "operator", "<<|"),
("main", "operator", "|>>"),
("main", "operator", "&<|"),
("main", "operator", "|&>"),
("main", "operator", "<^"),
("main", "operator", ">^"),
("main", "operator", "?#"),
("main", "operator", "?-"),
("main", "operator", "?|"),
("main", "operator", "?-|"),
("main", "operator", "?||"),
("main", "operator", "~="),
# network operators
# see https://www.postgresql.org/docs/current/functions-net.html
("main", "operator", "<<="),
("main", "operator", ">>="),
# json operators
# see https://www.postgresql.org/docs/current/functions-json.html
("main", "operator", "->"),
("main", "operator", "->>"),
("main", "operator", "#>"),
("main", "operator", "#>>"),
("main", "operator", "-|-"), # range adjacency
("main", "word_operator", "is"),
("main", "word_operator", "in"),
("main", "word_operator", "like"),
("main", "word_operator", "ilike"),
("main", "word_operator", "like any"),
("main", "word_operator", "any"),
("main", "word_operator", "some"),
("main", "word_operator", "exists"),
("main", "word_operator", "all"),
("main", "word_operator", "grouping sets"),
("main", "word_operator", "cube"),
("main", "word_operator", "rollup"),
("main", "as", "as"),
("main", "on", "on"),
("main", "boolean_operator", "AND"),
Expand All @@ -101,6 +160,11 @@ def test_rule_props_are_unique(self, polyglot: Polyglot) -> None:
("main", "unterm_keyword", "left join"),
("main", "unterm_keyword", "cross join"),
("main", "unterm_keyword", "join"),
("main", "unterm_keyword", "union"),
("main", "unterm_keyword", "union all"),
("main", "unterm_keyword", "intersect"),
("main", "unterm_keyword", "minus"),
("main", "unterm_keyword", "except"),
("main", "name", "my_table_45"),
("main", "newline", "\n"),
("jinja", "jinja_comment", "{# my comment #}"),
Expand Down
3 changes: 2 additions & 1 deletion tests/unit_tests/test_jinjafmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
import pytest

from sqlfmt.jinjafmt import JinjaFormatter, JinjaTag
from sqlfmt.line import Line, Node
from sqlfmt.line import Line
from sqlfmt.mode import Mode
from sqlfmt.node import Node
from sqlfmt.token import Token, TokenType


Expand Down

0 comments on commit e2e9286

Please sign in to comment.