Skip to content

Commit

Permalink
release 10.643.24144
Browse files Browse the repository at this point in the history
  • Loading branch information
klahnakoski committed May 23, 2024
2 parents 72f9110 + dcf057b commit a4379e6
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 33 deletions.
33 changes: 31 additions & 2 deletions mo_sql_parsing/keywords.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,19 @@
)
REGEXP = keyword("regexp").set_parser_name("rgx")
NEQ = (Literal("!=") | Literal("<>")).set_parser_name("neq")
LAMBDA = Literal("->").set_parser_name("lambda")
ASSIGN = Literal(":=").set_parser_name("assign")

JSON_GET = Literal("->").set_parser_name("json_get")
JSON_GET_TEXT = Literal("->>").set_parser_name("json_get_text")
JSON_PATH = Literal("#>").set_parser_name("json_path")
JSON_PATH_TEXT = Literal("#>>").set_parser_name("json_path_text")
JSON_SUBSUMES = Literal("@>").set_parser_name("json_subsumes")
JSON_SUBSUMED_BY = Literal("<@").set_parser_name("json_subsumed_by")
JSON_CONTAINS = Literal("?").set_parser_name("json_contains")
JSON_CONTAINS_ANY = Literal("?|").set_parser_name("json_contains_any")
JSON_CONTAINS_ALL = Literal("?&").set_parser_name("json_contains_all")
JSON_PATH_DEL = Literal("#-").set_parser_name("json_path_del")

AND = keyword("and")
APPLY = keyword("apply")
BEGIN = keyword("begin").suppress()
Expand Down Expand Up @@ -290,6 +300,16 @@
"validate_conversion": 0,
"collate": 0,
"concat": 1,
"json_get": 1.5,
"json_get_text": 1.5,
"json_path": 1.5,
"json_path_text": 1.5,
"json_subsumes": 1.5,
"json_subsumed_by": 1.5,
"json_contains": 1.5,
"json_contains_any": 1.5,
"json_contains_all": 1.5,
"json_path_del": 1.5,
"mul": 2,
"div": 1.5,
"mod": 2,
Expand Down Expand Up @@ -351,6 +371,16 @@
KNOWN_OPS = [
COLLATE,
CONCAT,
JSON_GET_TEXT
| JSON_GET
| JSON_PATH_TEXT
| JSON_PATH
| JSON_SUBSUMES
| JSON_SUBSUMED_BY
| JSON_CONTAINS_ANY
| JSON_CONTAINS_ALL
| JSON_CONTAINS
| JSON_PATH_DEL,
POS,
NEG,
MUL | DIV | MOD,
Expand Down Expand Up @@ -378,7 +408,6 @@
NOT,
AND,
OR,
LAMBDA,
ASSIGN,
REGEXP,
NOT_REGEXP,
Expand Down
34 changes: 11 additions & 23 deletions mo_sql_parsing/sql_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,10 @@ def matching(type):
+ ZeroOrMore(Group(simple_accessor | dynamic_accessor))
)

_lambda = Group(
LB + Group(delimited_list(identifier))("params") + RB + Literal("->").suppress() + expression("lambda")
)

with NO_WHITESPACE:

def scale(tokens):
Expand Down Expand Up @@ -355,6 +359,7 @@ def scale(tokens):
| create_array
| create_map
| create_struct
| _lambda
| (LB + Group(query) + RB)
| (LB + Group(delimited_list(expression)) / to_tuple_call + RB)
| literal_string
Expand Down Expand Up @@ -386,7 +391,7 @@ def scale(tokens):
o,
1 if o in unary_ops else (3 if isinstance(o, tuple) else 2),
unary_ops.get(o, LEFT_ASSOC),
to_lambda if o is LAMBDA else to_json_operator,
to_json_operator,
)
for o in KNOWN_OPS
],
Expand Down Expand Up @@ -769,7 +774,7 @@ def mult(tokens):
drops = assign(
"drop",
temporary
+MatchFirst([
+ MatchFirst([
keyword(item).suppress() + Optional(flag("if exists")) + Group(identifier)(item)
for item in ["table", "view", "index", "schema"]
]),
Expand Down Expand Up @@ -1055,16 +1060,8 @@ def mult(tokens):
+ keyword("end if").suppress()
)
leave = assign("leave", identifier)
while_block = (
assign("while", expression)
+ assign("do", many_command)
+ keyword("end while").suppress()
)
loop_block = (
keyword("loop").suppress()
+ many_command("loop")
+ keyword("end loop").suppress()
)
while_block = assign("while", expression) + assign("do", many_command) + keyword("end while").suppress()
loop_block = keyword("loop").suppress() + many_command("loop") + keyword("end loop").suppress()

create_trigger = assign(
"create trigger",
Expand Down Expand Up @@ -1134,25 +1131,16 @@ def mult(tokens):
)("declare_handler")

declare_cursor = Group(
keyword("declare").suppress()
+ identifier("name")
+ keyword("cursor for").suppress()
+ query("query")
keyword("declare").suppress() + identifier("name") + keyword("cursor for").suppress() + query("query")
)("declare_cursor")


transact = (
Group(keyword("start transaction")("op")) / to_json_call
| Group(keyword("commit")("op")) / to_json_call
| Group(keyword("rollback")("op")) / to_json_call
)

blocks = Group(Optional(identifier("label") + ":") + (
block
| if_block
| while_block
| loop_block
))
blocks = Group(Optional(identifier("label") + ":") + (block | if_block | while_block | loop_block))

#############################################################
# FINALLY ASSEMBLE THE PARSER
Expand Down
2 changes: 2 additions & 0 deletions mo_sql_parsing/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
MAP_TYPE = (keyword("map")("op") + LB + delimited_list(simple_types("params")) + RB) / to_json_call
ARRAY_TYPE = (keyword("array")("op") + LB + simple_types("params") + RB) / to_json_call
JSON = Group(keyword("json")("op")) / to_json_call
JSONB = Group(keyword("jsonb")("op")) / to_json_call

DATE = keyword("date")
DATETIME = keyword("datetime")
Expand Down Expand Up @@ -171,6 +172,7 @@
INT64,
BYTEINT,
JSON,
JSONB,
NCHAR,
NVARCHAR,
NUMBER,
Expand Down
16 changes: 10 additions & 6 deletions mo_sql_parsing/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,6 @@ def _chunk(values, size):
yield acc


def to_lambda(tokens):
params, op, expr = list(tokens)
return Call("lambda", [expr], {"params": list(params)})


def to_json_operator(tokens):
# ARRANGE INTO {op: params} FORMAT
length = len(tokens.tokens)
Expand Down Expand Up @@ -242,6 +237,16 @@ def to_tuple_call(token, index, string):
"COLLATE": "collate",
":": "get",
"||": "concat",
"->": "json_get",
"->>": "json_get_text",
"#>": "json_path",
"#>>": "json_path_text",
"@>": "json_subsumes",
"<@": "json_subsumed_by",
"?": "json_contains",
"?|": "json_contains_any",
"?&": "json_contains_all",
"#-": "json_path_del",
"*": "mul",
"/": "div",
"%": "mod",
Expand Down Expand Up @@ -279,7 +284,6 @@ def to_tuple_call(token, index, string):
"not_simlilar_to": "not_similar_to",
"or": "or",
"and": "and",
"->": "lambda",
":=": "assign",
"union": "union",
"union_all": "union_all",
Expand Down
2 changes: 1 addition & 1 deletion packaging/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
name='mo-sql-parsing',
packages=["mo_sql_parsing"],
url='https://github.com/klahnakoski/mo-sql-parsing',
version='10.642.24144',
version='10.643.24144',
zip_safe=True
)
2 changes: 1 addition & 1 deletion packaging/setuptools.json
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,6 @@
"name": "mo-sql-parsing",
"packages": ["mo_sql_parsing"],
"url": "https://github.com/klahnakoski/mo-sql-parsing",
"version": "10.642.24144",
"version": "10.643.24144",
"zip_safe": true
}
15 changes: 15 additions & 0 deletions tests/test_postgres.py
Original file line number Diff line number Diff line change
Expand Up @@ -529,3 +529,18 @@ def test_issue_175_extract_millennium(self):
result = parse(sql)
expected = {"select": {"value": {"extract": ["millennium", "date"]}}}
self.assertEqual(result, expected)

def test_issue_239_jsonb1(self):
sql = """select jsonb ->> 'field_key' FROM a"""
result = parse(sql)
expected = {"from": "a", "select": {"value": {"json_get_text": ["jsonb", {"literal": "field_key"}]}}}
self.assertEqual(result, expected)

def test_issue_239_jsonb2(self):
sql = """select name::jsonb ->> 'field_key' FROM a"""
result = parse(sql)
expected = {
"from": "a",
"select": {"value": {"json_get_text": [{"cast": ["name", {"jsonb": {}}]}, {"literal": "field_key"}]}},
}
self.assertEqual(result, expected)
2 changes: 2 additions & 0 deletions tests/test_sqlglot.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

from unittest import skip, TestCase

from mo_parsing.debug import Debugger

from mo_sql_parsing import parse


Expand Down

0 comments on commit a4379e6

Please sign in to comment.