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

V1.1.0 release #246

Merged
merged 2 commits into from
Apr 21, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
**v1.1.0**
### Improvements
MySQL:
1. Added support for INDEX statement inside table definition
2. Added support for MySQL INVISIBLE/VISIBLE statement - https://github.com/xnuinside/simple-ddl-parser/issues/243

Snowflake:
1. Added support for cluster by statement before columns definition - https://github.com/xnuinside/simple-ddl-parser/issues/234


**v1.0.4**
### Improvements
1. Support functions with schema prefix in `DEFAULT` and `CHECK` statements. https://github.com/xnuinside/simple-ddl-parser/issues/240
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,16 @@ for help with debugging & testing support for BigQuery dialect DDLs:


## Changelog
**v1.1.0**
### Improvements
MySQL:
1. Added support for INDEX statement inside table definition
2. Added support for MySQL INVISIBLE/VISIBLE statement - https://github.com/xnuinside/simple-ddl-parser/issues/243

Snowflake:
1. Added support for cluster by statement before columns definition - https://github.com/xnuinside/simple-ddl-parser/issues/234


**v1.0.4**
### Improvements
1. Support functions with schema prefix in `DEFAULT` and `CHECK` statements. https://github.com/xnuinside/simple-ddl-parser/issues/240
Expand Down
18 changes: 17 additions & 1 deletion docs/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ Big thanks for the involving & contribution with test cases with DDL samples & o


* https://github.com/kukigai ,
* https://github.com/Awalkman90 ,
* https://github.com/kliushnichenko ,
* https://github.com/geob3d

for help with debugging & testing support for BigQuery dialect DDLs:
Expand All @@ -549,6 +549,22 @@ for help with debugging & testing support for BigQuery dialect DDLs:
Changelog
---------

**v1.1.0**

Improvements
^^^^^^^^^^^^

MySQL:


#. Added support for INDEX statement inside table definition
#. Added support for MySQL INVISIBLE/VISIBLE statement - https://github.com/xnuinside/simple-ddl-parser/issues/243

Snowflake:


#. Added support for cluster by statement before columns definition - https://github.com/xnuinside/simple-ddl-parser/issues/234

**v1.0.4**

Improvements
Expand Down
6 changes: 5 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "simple-ddl-parser"
version = "1.0.4"
version = "1.1.0"
description = "Simple DDL Parser to parse SQL & dialects like HQL, TSQL (MSSQL), Oracle, AWS Redshift, Snowflake, MySQL, PostgreSQL, etc ddl files to json/python dict with full information about columns: types, defaults, primary keys, etc.; sequences, alters, custom types & other entities from ddl."
authors = ["Iuliia Volkova <xnuinside@gmail.com>"]
license = "MIT"
Expand All @@ -22,6 +22,10 @@ classifiers = [
"Topic :: Software Development :: Libraries :: Python Modules"
]

[[tool.poetry.source]]
name = "pypi-public"
url = "https://pypi.org/simple/"

[tool.poetry.dependencies]
python = "^3.6"
dataclasses = { version = "0.8", python = ">=3.6,<3.7" }
Expand Down
17 changes: 9 additions & 8 deletions simple_ddl_parser/ddl_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ def after_columns_tokens(self, t: LexToken) -> LexToken:
return t

def process_body_tokens(self, t: LexToken) -> LexToken:
if (
self.lexer.last_par == "RP" and not self.lexer.lp_open
) or self.lexer.after_columns:
if (self.lexer.last_par == "RP" and not self.lexer.lp_open) or (
self.lexer.after_columns and not self.lexer.columns_def
):
t = self.after_columns_tokens(t)
elif self.lexer.columns_def:
t.type = tok.columns_definition.get(t.value.upper(), t.type)
Expand All @@ -83,7 +83,6 @@ def tokens_not_columns_names(self, t: LexToken) -> LexToken:
t_tag = self.parse_tags_symbols(t)
if t_tag:
return t_tag

if "ARRAY" in t.value:
t.type = "ARRAY"
return t
Expand All @@ -98,7 +97,8 @@ def tokens_not_columns_names(self, t: LexToken) -> LexToken:
elif self.lexer.last_token != "COMMA":
t.type = tok.common_statements.get(t.value.upper(), t.type)
else:
t.type = tok.first_liners.get(t.value.upper(), t.type)
if not (self.lexer.columns_def and self.lexer.after_columns):
t.type = tok.first_liners.get(t.value.upper(), t.type)

# get tokens from other token dicts
t = self.process_body_tokens(t)
Expand Down Expand Up @@ -198,7 +198,6 @@ def t_ID(self, t: LexToken):
self.commat_type(t)

self.set_lexx_tags(t)

return self.set_last_token(t)

def commat_type(self, t: LexToken):
Expand All @@ -209,14 +208,16 @@ def capitalize_tokens(self, t: LexToken):
if t.type != "ID" and t.type not in ["LT", "RT"]:
t.value = t.value.upper()

def set_parathesis_tokens(self, t: LexToken):
def set_parenthesis_tokens(self, t: LexToken):
if t.type in ["RP", "LP"]:
if t.type == "RP" and self.lexer.lp_open:
self.lexer.lp_open -= 1
if not self.lexer.lp_open:
self.lexer.after_columns = True
self.lexer.last_par = t.type

def set_lexx_tags(self, t: LexToken):
self.set_parathesis_tokens(t)
self.set_parenthesis_tokens(t)

if t.type == "ALTER":
self.lexer.is_alter = True
Expand Down
15 changes: 10 additions & 5 deletions simple_ddl_parser/dialects/snowflake.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import re
from typing import List

from simple_ddl_parser.utils import remove_par
import re


class Snowflake:
Expand All @@ -11,12 +11,17 @@ def p_clone(self, p: List) -> None:
p[0] = {"clone": {"from": p_list[-1]}}

def p_expression_cluster_by(self, p: List) -> None:
"""expr : expr CLUSTER BY LP pid RP
| expr CLUSTER BY pid
"""
"""expr : expr cluster_by"""
p_list = list(p)
p[0] = p[1]
p[0].update(p_list[-1])

def p_cluster_by(self, p: List) -> None:
"""cluster_by : CLUSTER BY LP pid RP
| CLUSTER BY pid
"""
p_list = remove_par(list(p))
p[0]["cluster_by"] = p_list[-1]
p[0] = {"cluster_by": p_list[-1]}

def p_multi_id_or_string(self, p: List) -> None:
"""multi_id_or_string : id_or_string
Expand Down
55 changes: 40 additions & 15 deletions simple_ddl_parser/dialects/sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,26 @@ def p_index_table_name(self, p: List) -> None:
table_name = p_list[-1]
p[0].update({"schema": schema, "table_name": table_name})

def p_c_index(self, p: List) -> None:
"""c_index : INDEX LP index_pid RP
| INDEX id LP index_pid RP
| c_index INVISIBLE
| c_index VISIBLE"""
p_list = remove_par(p_list=list(p))
if isinstance(p_list[1], dict):
p[0] = p_list[1]
p[0]["details"] = {p_list[-1].lower(): True}
else:
if len(p_list) == 3:
name = None
else:
name = p_list[2]
p[0] = {
"index_stmt": True,
"name": name,
"columns": p_list[-1]["detailed_columns"],
}

def p_create_index(self, p: List) -> None:
"""create_index : CREATE INDEX id
| CREATE UNIQUE INDEX id
Expand Down Expand Up @@ -1020,7 +1040,9 @@ def p_expression_table(self, p: List) -> None: # noqa R701
| table_name LP defcolumn
| table_name
| table_name LP RP
| table_name cluster_by LP defcolumn
| expr COMMA defcolumn
| expr COMMA c_index
| expr COMMA
| expr COMMA constraint
| expr COMMA check_ex
Expand All @@ -1041,30 +1063,33 @@ def p_expression_table(self, p: List) -> None: # noqa R701
"""
p[0] = p[1] or defaultdict(list)
p_list = remove_par(list(p))
if len(p_list) > 2 and "cluster_by" in p_list[2]:
p[0].update(p_list[2])
if p_list[-1] != "," and p_list[-1] is not None:
if "type" in p_list[-1] and "name" in p_list[-1]:
if not p[0].get("columns"):
p[0]["columns"] = []
p[0]["columns"].append(p_list[-1])
elif "index_stmt" in p_list[-1]:
del p_list[-1]["index_stmt"]
if not p[0].get("index"):
p[0]["index"] = []
index_data = p_list[-1]
p[0]["index"].append(
{
"clustered": False,
"columns": [index_data["columns"]],
"detailed_columns": [
{
"name": index_data["columns"],
"nulls": "LAST",
"order": "ASC",
}
],
"index_name": index_data["name"],
"unique": False,
}
)
_index = {
"clustered": False,
"columns": [index_data["columns"]],
"detailed_columns": [
{
"name": index_data["columns"],
"nulls": "LAST",
"order": "ASC",
}
],
"index_name": index_data["name"],
"unique": False,
}
_index.update(index_data.get("details", {}))
p[0]["index"].append(_index)
elif "check" in p_list[-1]:
p[0] = self.extract_check_data(p, p_list)
elif "enforced" in p_list[-1]:
Expand Down
53,056 changes: 52,588 additions & 468 deletions simple_ddl_parser/parsetab.py

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions simple_ddl_parser/tokens.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
"WITH",
"ORDER",
"NOORDER",
"VISIBLE",
"INVISIBLE",
}
columns_definition = {value: value for value in columns_definition}
columns_definition[","] = "COMMA"
Expand All @@ -70,9 +72,12 @@
"CONSTRAINT",
"FOREIGN",
"PRIMARY",
"INDEX",
"UNIQUE",
"CHECK",
"WITH",
"CLUSTER",
"BY",
}
first_liners = {value: value for value in first_liners}

Expand Down
4 changes: 2 additions & 2 deletions tests/dialects/test_mssql_specific.py
Original file line number Diff line number Diff line change
Expand Up @@ -1876,7 +1876,7 @@ def test_constraint_primary_key():

ddl = """CREATE TABLE [dbo].[users_WorkSchedule](
[id] [int] IDENTITY(1,1) NOT NULL,
[user_id] [int] NULL),
[user_id] [int] NULL,
CONSTRAINT [PK_users_WorkSchedule_id] PRIMARY KEY CLUSTERED
(
[id] ASC
Expand All @@ -1885,7 +1885,7 @@ def test_constraint_primary_key():
CONSTRAINT [PK_users_WorkSchedule_id] PRIMARY KEY
(
[id] ASC
)
))
"""
result = DDLParser(ddl).run(group_by_type=True, output_mode="mssql")
assert result == expected
Expand Down
Loading
Loading