From 3e7289e5262d07ca6f5fd372f7c16fd5461fd932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alphan=20Y=C4=B1lmaz?= Date: Thu, 30 May 2024 16:30:43 +0200 Subject: [PATCH 1/6] Two more tests for issue 237 --- tests/test_sql_server.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/test_sql_server.py b/tests/test_sql_server.py index f413227..4780756 100644 --- a/tests/test_sql_server.py +++ b/tests/test_sql_server.py @@ -310,3 +310,29 @@ def test_issue_237_declare_var(self): "body": {"block": {"declare": {"default": 42, "name": "@MYVARIABLE", "type": {"int": {}},}}}, }} self.assertEqual(result, expected) + + def test_issue_237_declare_var_with_as(self): + sql = """create procedure k() BEGIN + DECLARE @MYVARIABLE AS INT = 42; + END""" + result = parse(sql) + expected = {"create_procedure": { + "name": "k", + "body": {"block": {"declare": {"default": 42, "name": "@MYVARIABLE", "type": {"int": {}},}}}, + }} + self.assertEqual(result, expected) + + def test_issue_237_declare_multiple_vars(self): + sql = """create procedure k() BEGIN + DECLARE @MYVAR INT, @MYOTHERVAR DATE; + END""" + result = parse(sql) + expected = { + "create_procedure": { + "name": "k", + "body": {"block": [ + {"declare": {"name": "@MYFIRSTVAR", "type": {"int": {}}}}, + {"declare": {"name": "@MYOTHERVAR", "type": {"int": {}}}}, + ]}, + }} + self.assertEqual(result, expected) From 0e7465826234e1409a8b14be72c2c4236a10d61c Mon Sep 17 00:00:00 2001 From: Kyle Lahnakoski Date: Thu, 30 May 2024 23:08:31 -0400 Subject: [PATCH 2/6] updates from other projects --- mo_sql_parsing/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mo_sql_parsing/__init__.py b/mo_sql_parsing/__init__.py index a6fe2e5..2e3dd54 100644 --- a/mo_sql_parsing/__init__.py +++ b/mo_sql_parsing/__init__.py @@ -23,6 +23,7 @@ "bigquery_parser": {"*": None, None: None}, } + SQL_NULL: Mapping[str, Mapping] = {"null": {}} From 9cb5e1ddcd79bb62030e1fb935fdb46538fd55e7 Mon Sep 17 00:00:00 2001 From: Kyle Lahnakoski Date: Thu, 30 May 2024 23:08:39 -0400 Subject: [PATCH 3/6] update version number --- packaging/setup.py | 2 +- packaging/setuptools.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/setup.py b/packaging/setup.py index b6a4f68..19b43b3 100644 --- a/packaging/setup.py +++ b/packaging/setup.py @@ -15,6 +15,6 @@ name='mo-sql-parsing', packages=["mo_sql_parsing"], url='https://github.com/klahnakoski/mo-sql-parsing', - version='10.645.24152', + version='10.646.24152', zip_safe=True ) \ No newline at end of file diff --git a/packaging/setuptools.json b/packaging/setuptools.json index b966fc5..f6ec333 100644 --- a/packaging/setuptools.json +++ b/packaging/setuptools.json @@ -311,6 +311,6 @@ "name": "mo-sql-parsing", "packages": ["mo_sql_parsing"], "url": "https://github.com/klahnakoski/mo-sql-parsing", - "version": "10.645.24152", + "version": "10.646.24152", "zip_safe": true } \ No newline at end of file From 18d36a86d7a5a64e49e80cf4018b50d1dfebcb3e Mon Sep 17 00:00:00 2001 From: Kyle Lahnakoski Date: Thu, 30 May 2024 23:11:17 -0400 Subject: [PATCH 4/6] black --- mo_sql_parsing/__init__.py | 1 - mo_sql_parsing/formatting.py | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/mo_sql_parsing/__init__.py b/mo_sql_parsing/__init__.py index 2e3dd54..a6fe2e5 100644 --- a/mo_sql_parsing/__init__.py +++ b/mo_sql_parsing/__init__.py @@ -23,7 +23,6 @@ "bigquery_parser": {"*": None, None: None}, } - SQL_NULL: Mapping[str, Mapping] = {"null": {}} diff --git a/mo_sql_parsing/formatting.py b/mo_sql_parsing/formatting.py index 45e124f..d13b534 100644 --- a/mo_sql_parsing/formatting.py +++ b/mo_sql_parsing/formatting.py @@ -113,7 +113,7 @@ def isolate(expr, sql, prec): "where", "groupby", "having", - "union_all" + "union_all", ] ordered_clauses = [ @@ -274,7 +274,7 @@ def wordy(v): # WITHIN GROUP ( # ORDER BY public.persentil.sale # ) - ob = self.orderby(json['within'], 100) + ob = self.orderby(json["within"], 100) parts.append(f"WITHIN GROUP ({ob})") if "name" in json: parts.extend(["AS", self.dispatch(json["name"])]) @@ -590,7 +590,7 @@ def unordered_query(self, json, prec): part for clause in unordered_clauses if clause in json - for part in [getattr(self, clause)(json, precedence[clause]+1)] + for part in [getattr(self, clause)(json, precedence[clause] + 1)] if part ) if prec > precedence["from"]: @@ -604,7 +604,7 @@ def with_(self, json, prec): return f"WITH {parts}" def union_all(self, json, prec): - sql = "\nUNION ALL\n".join(self.dispatch(part) for part in listwrap(json['union_all'])) + sql = "\nUNION ALL\n".join(self.dispatch(part) for part in listwrap(json["union_all"])) return f"{sql}" if prec > precedence["union_all"] else f"({sql})" def select(self, json, prec): From fe45f6173fc989310c5240befc92513e1701eab8 Mon Sep 17 00:00:00 2001 From: Kyle Lahnakoski Date: Fri, 31 May 2024 00:07:29 -0400 Subject: [PATCH 5/6] fix more declares --- mo_sql_parsing/sql_parser.py | 3 +-- mo_sql_parsing/types.py | 13 ++++++++++--- tests/test_sql_server.py | 28 ++++++++++++++++++++-------- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/mo_sql_parsing/sql_parser.py b/mo_sql_parsing/sql_parser.py index aa28fb1..40c3eaa 100644 --- a/mo_sql_parsing/sql_parser.py +++ b/mo_sql_parsing/sql_parser.py @@ -61,7 +61,7 @@ def parser(literal_string, simple_ident, all_columns=None, sqlserver=False): # EXPRESSIONS expression = Forward() - (column_type, column_definition, column_def_references, column_option,) = get_column_type( + (column_type, column_definition, column_def_references, column_option, declare_variable) = get_column_type( expression, identifier, literal_string ) proc_param = Group( @@ -912,7 +912,6 @@ def mult(tokens): ############################################################# statement = Forward() special_ident = keyword("masking policy") | identifier / (lambda t: t[0].lower()) - declare_variable = assign("declare", column_definition) set_one_variable = SET + ( (special_ident + Optional(EQ) + expression) / (lambda t: {t[0].lower(): t[1].lower() if isinstance(t[1], str) else t[1]}) diff --git a/mo_sql_parsing/types.py b/mo_sql_parsing/types.py index cd9b7a3..b41b947 100644 --- a/mo_sql_parsing/types.py +++ b/mo_sql_parsing/types.py @@ -21,7 +21,7 @@ RIGHT_ASSOC, LEFT_ASSOC, Keyword, - Combine, + Combine, Empty, ) from mo_sql_parsing.keywords import ( @@ -266,13 +266,20 @@ def get_column_type(expr, identifier, literal_string): | assign("check", LB + expr + RB) | assign("default", expr) | assign("on update", expr) - | (EQ + expr)("default") ) column_definition << Group( identifier("name") + (column_type | identifier("type")) + ZeroOrMore(column_options) ) / to_flat_column_type + variable_options = ( + assign("default", expr) + | EQ + expr("default") + ) + declare_variable = assign("declare", delimited_list(Group( + identifier("name") + Optional(AS) + simple_types("type") + ZeroOrMore(variable_options) + ))) + set_parser_names() - return column_type, column_definition, column_def_references, column_options + return column_type, column_definition, column_def_references, column_options, declare_variable diff --git a/tests/test_sql_server.py b/tests/test_sql_server.py index 4780756..be6d5b2 100644 --- a/tests/test_sql_server.py +++ b/tests/test_sql_server.py @@ -9,8 +9,6 @@ from unittest import TestCase -from mo_parsing.debug import Debugger - from mo_sql_parsing import parse_sqlserver as parse @@ -307,7 +305,7 @@ def test_issue_237_declare_var(self): result = parse(sql) expected = {"create_procedure": { "name": "k", - "body": {"block": {"declare": {"default": 42, "name": "@MYVARIABLE", "type": {"int": {}},}}}, + "body": {"block": {"declare": {"default": 42, "name": "@MYVARIABLE", "type": {"int": {}}, }}}, }} self.assertEqual(result, expected) @@ -318,7 +316,7 @@ def test_issue_237_declare_var_with_as(self): result = parse(sql) expected = {"create_procedure": { "name": "k", - "body": {"block": {"declare": {"default": 42, "name": "@MYVARIABLE", "type": {"int": {}},}}}, + "body": {"block": {"declare": {"default": 42, "name": "@MYVARIABLE", "type": {"int": {}}}}}, }} self.assertEqual(result, expected) @@ -327,12 +325,26 @@ def test_issue_237_declare_multiple_vars(self): DECLARE @MYVAR INT, @MYOTHERVAR DATE; END""" result = parse(sql) - expected = { - "create_procedure": { + expected = {"create_procedure": { + "name": "k", + "body": {"block": {"declare": [ + {"name": "@MYVAR", "type": {"int": {}}}, + {"name": "@MYOTHERVAR", "type": {"date": {}}}, + ]}}, + }} + self.assertEqual(result, expected) + + def test_issue_237_declare_multiple_vars_with_code(self): + sql = """create procedure k() BEGIN + DECLARE @MYVAR INT, @MYOTHERVAR DATE; + SELECT a FROM rental; + END""" + result = parse(sql) + expected = {"create_procedure": { "name": "k", "body": {"block": [ - {"declare": {"name": "@MYFIRSTVAR", "type": {"int": {}}}}, - {"declare": {"name": "@MYOTHERVAR", "type": {"int": {}}}}, + {"declare": [{"name": "@MYVAR", "type": {"int": {}}}, {"name": "@MYOTHERVAR", "type": {"date": {}}}]}, + {"select": {"value": "a"}, "from": "rental"}, ]}, }} self.assertEqual(result, expected) From e12cebb045408e83d0a43a8681b1885902834805 Mon Sep 17 00:00:00 2001 From: Kyle Lahnakoski Date: Fri, 31 May 2024 00:12:50 -0400 Subject: [PATCH 6/6] black --- mo_sql_parsing/types.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/mo_sql_parsing/types.py b/mo_sql_parsing/types.py index b41b947..849a51d 100644 --- a/mo_sql_parsing/types.py +++ b/mo_sql_parsing/types.py @@ -21,7 +21,8 @@ RIGHT_ASSOC, LEFT_ASSOC, Keyword, - Combine, Empty, + Combine, + Empty, ) from mo_sql_parsing.keywords import ( @@ -272,13 +273,11 @@ def get_column_type(expr, identifier, literal_string): identifier("name") + (column_type | identifier("type")) + ZeroOrMore(column_options) ) / to_flat_column_type - variable_options = ( - assign("default", expr) - | EQ + expr("default") + variable_options = assign("default", expr) | EQ + expr("default") + declare_variable = assign( + "declare", + delimited_list(Group(identifier("name") + Optional(AS) + simple_types("type") + ZeroOrMore(variable_options))), ) - declare_variable = assign("declare", delimited_list(Group( - identifier("name") + Optional(AS) + simple_types("type") + ZeroOrMore(variable_options) - ))) set_parser_names()