Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions sqlparse/keywords.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ def find_delimited_spans(text):
(r'[;:()\[\],\.]', tokens.Punctuation),
# JSON operators
(r'(\->>?|#>>?|@>|<@|\?\|?|\?&|\-|#\-)', tokens.Operator),
# PostgreSQL case-insensitive regular-expression and LIKE operators.
(r'!?~~?\*', tokens.Operator.Comparison),
(r'[<>=~!]+', tokens.Operator.Comparison),
(r'[+/@#%^&|^-]+', tokens.Operator),
]
Expand Down
39 changes: 39 additions & 0 deletions tests/test_pattern_operators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import pytest

import sqlparse
from sqlparse import lexer, sql
from sqlparse import tokens as T


@pytest.mark.parametrize('operator', ['~*', '!~*', '~~*', '!~~*'])
def test_pattern_operator_token_and_group(operator):
assert list(lexer.tokenize(operator)) == [(T.Operator.Comparison, operator)]
parsed = sqlparse.parse(f"name {operator} 'pattern'")[0]
assert len(parsed.tokens) == 1
assert isinstance(parsed.tokens[0], sql.Comparison)
assert parsed.tokens[0].tokens[2].value == operator
assert parsed.tokens[0].right.value == "'pattern'"


@pytest.mark.parametrize('operator', ['~*', '!~*', '~~*', '!~~*'])
@pytest.mark.parametrize('separator', ['', ' '])
def test_pattern_operator_spacing(operator, separator):
text = f"SELECT name{separator}{operator}{separator}'pattern' FROM tab"
expected = f"SELECT name {operator} 'pattern' FROM tab"
assert sqlparse.format(text, use_space_around_operators=True) == expected
assert sqlparse.format(expected, use_space_around_operators=True) == expected


def test_issue613_operator_spacing():
text = "SELECT ARRAY[1] <@ ARRAY[1, 2], 'a' !~* 'xyz'"
assert sqlparse.format(text, use_space_around_operators=True) == text


@pytest.mark.parametrize('text, expected', [
('SELECT a*b, * FROM tab', 'SELECT a * b, * FROM tab'),
("SELECT '~*', '!~~*', * FROM tab", "SELECT '~*', '!~~*', * FROM tab"),
("SELECT name ~ * 'pattern'", "SELECT name ~ * 'pattern'"),
("SELECT name ~/* keep */*'pattern'", "SELECT name ~ /* keep */*'pattern'"),
])
def test_pattern_operator_controls(text, expected):
assert sqlparse.format(text, use_space_around_operators=True) == expected