Skip to content

Commit

Permalink
Merge pull request #113 from xnuinside/v0.25.0_release
Browse files Browse the repository at this point in the history
silent=False flag and at time zone
  • Loading branch information
xnuinside authored Feb 7, 2022
2 parents 304cdd0 + fe75098 commit 865ec90
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 10 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
**v0.25.0**
## Fixes:

1. Fix for issue with 'at time zone' https://github.com/xnuinside/simple-ddl-parser/issues/112

## New features:

1. Added flag to raise errors if parser cannot parse statement DDLParser(.., silent=False) - https://github.com/xnuinside/simple-ddl-parser/issues/109


**v0.24.2**
## Fixes:

Expand Down
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,15 @@ To dump result in json use argument .run(dump=True)

You also can provide a path where you want to have a dumps with schema with argument .run(dump_path='folder_that_use_for_dumps/')


### Raise error if DDL cannot be parsed by Parser

By default Parser does not raise the error if some statement cannot be parsed - and just skip & produce empty output.

To change this behavior you can pass 'silent=False' argumen to main parser class, like:

DDLParser(.., silent=False)

## Supported Statements

- CREATE TABLE [ IF NOT EXISTS ] + columns defenition, columns attributes: column name + type + type size(for example, varchar(255)), UNIQUE, PRIMARY KEY, DEFAULT, CHECK, NULL/NOT NULL, REFERENCES, ON DELETE, ON UPDATE, NOT DEFERRABLE, DEFERRABLE INITIALLY, GENERATED ALWAYS, STORED, COLLATE
Expand Down Expand Up @@ -393,6 +402,16 @@ https://github.com/swiatek25


## Changelog
**v0.25.0**
## Fixes:

1. Fix for issue with 'at time zone' https://github.com/xnuinside/simple-ddl-parser/issues/112

## New features:

1. Added flag to raise errors if parser cannot parse statement DDLParser(.., silent=False) - https://github.com/xnuinside/simple-ddl-parser/issues/109


**v0.24.2**
## Fixes:

Expand Down
26 changes: 26 additions & 0 deletions docs/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,18 @@ To dump result in json use argument .run(dump=True)

You also can provide a path where you want to have a dumps with schema with argument .run(dump_path='folder_that_use_for_dumps/')

Raise error if DDL cannot be parsed by Parser
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

By default Parser does not raise the error if some statement cannot be parsed - and just skip & produce empty output.

To change this behavior you can pass 'silent=False' argumen to main parser class, like:

.. code-block::
DDLParser(.., silent=False)
Supported Statements
--------------------

Expand Down Expand Up @@ -453,6 +465,20 @@ https://github.com/swiatek25
Changelog
---------

**v0.25.0**

Fixes:
------


#. Fix for issue with 'at time zone' https://github.com/xnuinside/simple-ddl-parser/issues/112

New features:
-------------


#. Added flag to raise errors if parser cannot parse statement DDLParser(.., silent=False) - https://github.com/xnuinside/simple-ddl-parser/issues/109

**v0.24.2**

Fixes:
Expand Down
2 changes: 1 addition & 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 = "0.24.2"
version = "0.25.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 Down
5 changes: 3 additions & 2 deletions simple_ddl_parser/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from simple_ddl_parser.ddl_parser import DDLParser, parse_from_file
from simple_ddl_parser.ddl_parser import (DDLParser, DDLParserError,
parse_from_file)

__all__ = ["DDLParser", "parse_from_file"]
__all__ = ["DDLParser", "parse_from_file", "DDLParserError"]
10 changes: 7 additions & 3 deletions simple_ddl_parser/ddl_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
from simple_ddl_parser.parser import Parser


class DDLParserError(Exception):
pass


class DDLParser(
Parser, Snowflake, BaseSQL, HQL, MySQL, MSSQL, Oracle, Redshift, BigQuery
):
Expand Down Expand Up @@ -172,7 +176,6 @@ def set_lexx_tags(self, t):

def set_last_token(self, t):
self.lexer.last_token = t.type

return t

def p_id(self, p):
Expand All @@ -182,10 +185,11 @@ def p_id(self, p):
p[0] = p[1]

def t_error(self, t):
raise SyntaxError("Unknown symbol %r" % (t.value[0],))
raise DDLParserError("Unknown symbol %r" % (t.value[0],))

def p_error(self, p):
pass
if not self.silent:
raise DDLParserError(f"Unknown statement at {p}")


def parse_from_file(file_path: str, **kwargs) -> List[Dict]:
Expand Down
8 changes: 6 additions & 2 deletions simple_ddl_parser/dialects/sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -1056,14 +1056,18 @@ def p_default(self, p: List) -> None:
| default FOR dot_id
| DEFAULT funct_expr
| DEFAULT LP pid RP
| DEFAULT LP funct_expr pid RP
| default id
| default LP RP
"""
p_list = list(p)
p_list = remove_par(list(p))

default = self.pre_process_default(p_list)

if not isinstance(default, dict) and default.isnumeric():
if isinstance(p_list[-1], list):
p_list[-1] = " ".join(p_list[-1])
default = " ".join(p_list[1:])
elif not isinstance(default, dict) and default.isnumeric():
default = int(default)

if isinstance(p[1], dict):
Expand Down
3 changes: 2 additions & 1 deletion simple_ddl_parser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ class Parser:
Subclass must include tokens for parser and rules
"""

def __init__(self, content: str) -> None:
def __init__(self, content: str, silent: bool = True) -> None:
"""init parser for file"""
self.tables = []
self.silent = silent
self.data = content.encode("unicode_escape")
self.paren_count = 0
self.lexer = lex.lex(object=self, debug=False)
Expand Down
17 changes: 16 additions & 1 deletion tests/non_statement_tests/test_common.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from simple_ddl_parser import DDLParser
import pytest

from simple_ddl_parser import DDLParser, DDLParserError


def test_no_unexpected_logs(capsys):
Expand All @@ -18,3 +20,16 @@ def test_no_unexpected_logs(capsys):
out, err = capsys.readouterr()
assert out == ""
assert err == ""


def test_silent_false_flag():
ddl = """
CREATE TABLE foo
(
created_timestamp TIMESTAMPTZ NOT NULL DEFAULT ALTER (now() at time zone 'utc')
);
"""
with pytest.raises(DDLParserError) as e:
DDLParser(ddl, silent=False).run(group_by_type=True)

assert "Unknown statement" in e.value[1]
64 changes: 64 additions & 0 deletions tests/test_simple_ddl_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2496,3 +2496,67 @@ def test_table_name_reserved_word_after_dot():
"types": [],
}
assert expected == result


def test_add_timezone():
ddl = """
CREATE TABLE foo
(
bar_timestamp bigint DEFAULT 1002 * extract(epoch from now()) * 1000,
bar_timestamp2 bigint DEFAULT (1002 * extract(epoch from now()) * 1000),
created_timestamp TIMESTAMPTZ NOT NULL DEFAULT (now() at time zone 'utc')
);
"""
result = DDLParser(ddl).run(group_by_type=True)
expected = {
"ddl_properties": [],
"domains": [],
"schemas": [],
"sequences": [],
"tables": [
{
"alter": {},
"checks": [],
"columns": [
{
"check": None,
"default": "1002 * extract(epoch from now()) * 1000",
"name": "bar_timestamp",
"nullable": True,
"references": None,
"size": None,
"type": "bigint",
"unique": False,
},
{
"check": None,
"default": "1002 * extract(epoch from now()) * 1000",
"name": "bar_timestamp2",
"nullable": True,
"references": None,
"size": None,
"type": "bigint",
"unique": False,
},
{
"check": None,
"default": "DEFAULT now() at time zone 'utc'",
"name": "created_timestamp",
"nullable": False,
"references": None,
"size": None,
"type": "TIMESTAMPTZ",
"unique": False,
},
],
"index": [],
"partitioned_by": [],
"primary_key": [],
"schema": None,
"table_name": "foo",
"tablespace": None,
}
],
"types": [],
}
assert expected == result

0 comments on commit 865ec90

Please sign in to comment.