Repository: shinichi-takii/ddlparse

Issue:
Postgres/Redshift : Not parse DDL of "::" syntax in field attribute
## Example
### DDL (Redshift)
```sql
CREATE TABLE IF NOT EXISTS "sample_schema"."sample_table"
(
	"div_cd" VARCHAR(2) NOT NULL
	,"div_name" VARCHAR(30) NOT NULL
	,"org_cd" VARCHAR(8) NOT NULL
	,"org_name" VARCHAR(60) NOT NULL
	,"team_cd" VARCHAR(2) NOT NULL
	,"team_name" VARCHAR(120) NOT NULL
	,"personal_cd" VARCHAR(7) NOT NULL
	,"personal_name" VARCHAR(300) NOT NULL
	,"username" VARCHAR(6) NOT NULL
	,"staff_flg" CHAR(1)  DEFAULT '0'::bpchar ENCODE lzo
	,"leader_flg" CHAR(1)  DEFAULT '0'::bpchar ENCODE lzo
)
DISTSTYLE EVEN
;
```

### ddlparse output BigQuery JSON schema
Not parse `leader_flg` field.
```javascript
[{
	"name": "div_cd", "type": "STRING", "mode": "REQUIRED"
}, {
	"name": "div_name", "type": "STRING", "mode": "REQUIRED"
}, {
	"name": "org_cd", "type": "STRING", "mode": "REQUIRED"
}, {
	"name": "org_name", "type": "STRING", "mode": "REQUIRED"
}, {
	"name": "team_cd", "type": "STRING", "mode": "REQUIRED"
}, {
	"name": "team_name", "type": "STRING", "mode": "REQUIRED"
}, {
	"name": "personal_cd", "type": "STRING", "mode": "REQUIRED"
}, {
	"name": "personal_name", "type": "STRING", "mode": "REQUIRED"
}, {
	"name": "username", "type": "STRING", "mode": "REQUIRED"
}, {
	"name": "staff_flg", "type": "STRING", "mode": "NULLABLE"
}]
```

Discussion:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 405a366..55f0b1d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
 
+## [1.6.1] - 2020-08-08
+### Fixed
+- Fix parse Redshift `ENCODE` attribute.
+
+
 ## [1.6.0] - 2020-07-18
 ### Added
 - Add property.
@@ -161,6 +166,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Initial released.
 
 
+[1.6.1]: https://github.com/shinichi-takii/ddlparse/compare/v1.6.0...v1.6.1
 [1.6.0]: https://github.com/shinichi-takii/ddlparse/compare/v1.5.0...v1.6.0
 [1.5.0]: https://github.com/shinichi-takii/ddlparse/compare/v1.4.0...v1.5.0
 [1.4.0]: https://github.com/shinichi-takii/ddlparse/compare/v1.3.1...v1.4.0
diff --git a/ddlparse/__init__.py b/ddlparse/__init__.py
index 4a21d65..1e327c9 100644
--- a/ddlparse/__init__.py
+++ b/ddlparse/__init__.py
@@ -8,7 +8,7 @@
 from .ddlparse import *
 
 __copyright__    = 'Copyright (C) 2018-2020 Shinichi Takii'
-__version__      = '1.6.0'
+__version__      = '1.6.1'
 __license__      = 'BSD-3-Clause'
 __author__       = 'Shinichi Takii'
 __author_email__ = 'shinichi.takii@gmail.com'
diff --git a/ddlparse/ddlparse.py b/ddlparse/ddlparse.py
index c960ef8..0dc81e6 100644
--- a/ddlparse/ddlparse.py
+++ b/ddlparse/ddlparse.py
@@ -505,13 +505,11 @@ class DdlParse(DdlParseBase):
     (
         (
             \s*\b(?:NOT\s+)NULL?\b
-        )?
-        (
+        )?(
             \s*\bAUTO_INCREMENT\b
         )?(
             \s*\b(UNIQUE|PRIMARY)(?:\s+KEY)?\b
-        )?
-        (
+        )?(
             \s*\bDEFAULT\b\s+(
                 ([A-Za-z0-9_\.\'\" -]|[^\x01-\x7E])*\:\:[A-Za-z0-9\[\]]+
                 |
@@ -521,8 +519,7 @@ class DdlParse(DdlParseBase):
                 |
                 [^,]+
             )
-        )?
-        (
+        )?(
             \s*\bCOMMENT\b\s+(
                 \'(\\\'|[^\']|,)+\'
                 |
@@ -530,6 +527,12 @@ class DdlParse(DdlParseBase):
                 |
                 [^,]+
             )
+        )?(
+            \s*\bENCODE\s+\w+\b
+        )?(
+            \s*\b(?:NOT\s+)NULL?\b
+        )?(
+            \s*\b(UNIQUE|PRIMARY)(?:\s+KEY)?\b
         )?
     )
     """


Test patch:
diff --git a/test/test_ddlparse.py b/test/test_ddlparse.py
index 76d1515..083ec18 100644
--- a/test/test_ddlparse.py
+++ b/test/test_ddlparse.py
@@ -321,8 +321,8 @@ TEST_DATA = {
         "ddl":
             """
             CREATE TABLE Sample_Table (
-              Col_01 char(1) DEFAULT '0'::bpchar,
-              Col_02 char(1) DEFAULT '0'::bpchar,
+              Col_01 char(1) DEFAULT '0'::bpchar PRIMARY KEY,
+              Col_02 char(1) DEFAULT '0'::bpchar ENCODE lzo NOT NULL,
               Col_03 integer DEFAULT 0,
               Col_04 numeric(10) DEFAULT 0,
               Col_05 numeric(20,3) DEFAULT 0.0,
@@ -333,8 +333,8 @@ TEST_DATA = {
         "database": None,
         "table": {"schema": None, "name": "Sample_Table", "temp": False},
         "columns": [
-            {"name": "Col_01", "type": "CHAR", "length": 1, "scale": None, "array_dimensional": 0, "is_unsigned": False, "is_zerofill": False, "not_null": False, "pk": False, "unique": False, "constraint": "", "description": None},
-            {"name": "Col_02", "type": "CHAR", "length": 1, "scale": None, "array_dimensional": 0, "is_unsigned": False, "is_zerofill": False, "not_null": False, "pk": False, "unique": False, "constraint": "", "description": None},
+            {"name": "Col_01", "type": "CHAR", "length": 1, "scale": None, "array_dimensional": 0, "is_unsigned": False, "is_zerofill": False, "not_null": True, "pk": True, "unique": False, "constraint": "PRIMARY KEY", "description": None},
+            {"name": "Col_02", "type": "CHAR", "length": 1, "scale": None, "array_dimensional": 0, "is_unsigned": False, "is_zerofill": False, "not_null": True, "pk": False, "unique": False, "constraint": "NOT NULL", "description": None},
             {"name": "Col_03", "type": "INTEGER", "length": None, "scale": None, "array_dimensional": 0, "is_unsigned": False, "is_zerofill": False, "not_null": False, "pk": False, "unique": False, "constraint": "", "description": None},
             {"name": "Col_04", "type": "NUMERIC", "length": 10, "scale": None, "array_dimensional": 0, "is_unsigned": False, "is_zerofill": False, "not_null": False, "pk": False, "unique": False, "constraint": "", "description": None},
             {"name": "Col_05", "type": "NUMERIC", "length": 20, "scale": 3, "array_dimensional": 0, "is_unsigned": False, "is_zerofill": False, "not_null": False, "pk": False, "unique": False, "constraint": "", "description": None},
@@ -342,8 +342,8 @@ TEST_DATA = {
             {"name": "Col_07", "type": "CHARACTER VARYING", "length": None, "scale": None, "array_dimensional": 1, "is_unsigned": False, "is_zerofill": False, "not_null": False, "pk": False, "unique": False, "constraint": "", "description": None},
         ],
         "bq_field": [
-            '{"name": "Col_01", "type": "STRING", "mode": "NULLABLE"}',
-            '{"name": "Col_02", "type": "STRING", "mode": "NULLABLE"}',
+            '{"name": "Col_01", "type": "STRING", "mode": "REQUIRED"}',
+            '{"name": "Col_02", "type": "STRING", "mode": "REQUIRED"}',
             '{"name": "Col_03", "type": "INTEGER", "mode": "NULLABLE"}',
             '{"name": "Col_04", "type": "INTEGER", "mode": "NULLABLE"}',
             '{"name": "Col_05", "type": "NUMERIC", "mode": "NULLABLE"}',