{"id":7718,"library":"simple-ddl-parser","title":"Simple DDL Parser","description":"Simple DDL Parser is a Python library designed to parse SQL DDL (Data Definition Language) files from various dialects, including HQL, TSQL (MSSQL), Oracle, AWS Redshift, Snowflake, MySQL, and PostgreSQL. It extracts comprehensive information about database entities like tables, columns (types, defaults, primary keys), sequences, alters, and custom types into a JSON or Python dictionary format. The library is actively maintained with frequent releases, currently at version 1.13.0, and typically sees rapid updates with more than 12 releases per year.","status":"active","version":"1.13.0","language":"en","source_language":"en","source_url":"https://github.com/xnuinside/simple-ddl-parser","tags":["sql","ddl","parser","schema","database","hql","tsql","oracle","redshift","snowflake","mysql","postgresql","code-analysis"],"install":[{"cmd":"pip install simple-ddl-parser","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Used for lexing and parsing (lex & yacc in Python).","package":"ply","optional":false},{"reason":"Requires Python 3.9 or higher. Support for Python 3.7 and 3.8 was deprecated in v1.8.0.","package":"python","optional":false}],"imports":[{"symbol":"DDLParser","correct":"from simple_ddl_parser import DDLParser"},{"symbol":"parse_from_file","correct":"from simple_ddl_parser import parse_from_file"}],"quickstart":{"code":"from simple_ddl_parser import DDLParser\n\nddl_statement = \"\"\"\nCREATE TABLE users (\n    user_id INT PRIMARY KEY,\n    username VARCHAR(50) NOT NULL UNIQUE,\n    email VARCHAR(100),\n    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);\n\"\"\"\n\nparser = DDLParser(ddl_statement)\nparsed_data = parser.run()\n\nprint(parsed_data)\n\n# Example with dialect-specific output (e.g., HQL)\nhql_ddl = \"\"\"\nCREATE EXTERNAL TABLE IF NOT EXISTS database.table_name (\n    day_long_nm string,\n    calendar_dt date,\n    source_batch_id string\n)\nPARTITIONED BY (batch_id int)\nSTORED AS PARQUET\nLOCATION 's3://datalake/table_name/v1';\n\"\"\"\nhql_parser = DDLParser(hql_ddl)\nhql_parsed_data = hql_parser.run(output_mode='hql')\nprint(hql_parsed_data)","lang":"python","description":"This quickstart demonstrates how to parse a DDL statement using the `DDLParser` class. It shows a basic table creation and an example of parsing an HQL statement with the `output_mode='hql'` argument to extract dialect-specific details like `EXTERNAL` or `LOCATION`."},"warnings":[{"fix":"Upgrade your Python environment to 3.9 or newer.","message":"Python 3.7 and 3.8 are no longer supported. The minimum required Python version is now 3.9.","severity":"breaking","affected_versions":">=1.8.0"},{"fix":"Update your code to expect `[''field'']` instead of `''('field')'` for bracketed arguments. Review custom parsing logic that might rely on older tokenization of `=` and `IN`.","message":"The output structure for arguments within brackets (e.g., `NULL_IF=('field')`) changed from a single string to a list of strings. Additionally, `=` and `IN` keywords are now parsed as separate tokens, which might affect custom processing of the output.","severity":"breaking","affected_versions":">=1.6.0"},{"fix":"Adjust your code to handle the new output schema for PostgreSQL's `TIME ZONE` and BigQuery's `RANGE_BUCKETS` and `*_TRUNC` constructs.","message":"For PostgreSQL, `TIME ZONE` is now an explicit boolean keyword `with_time_zone` instead of being part of the type definition. For BigQuery, `RANGE_BUCKETS` range is now in its own `range` keyword, and `*_TRUNC` functions' second argument moved to `trunc_by`.","severity":"breaking","affected_versions":">=1.3.0"},{"fix":"Initialize the parser with `DDLParser(ddl_string, silent=False)` to force it to raise a `DDLParserError` on unparsable statements. Alternatively, inspect the output carefully for missing entities.","message":"By default, the parser does not raise an error if a statement cannot be parsed; instead, it silently skips the problematic statement and may produce incomplete or empty output. This can make debugging difficult.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Ensure you are using a recent version of `simple-ddl-parser` (fix was included in `v0.26.0` and later). If the issue persists with other `IN` clauses, consider rewriting the `CHECK` statement using `OR` conditions or report an issue.","cause":"The parser failed to understand a `CHECK` constraint using the `IN` keyword, e.g., `CHECK(col IN ('val1', 'val2'))`.","error":"DDLParserError: Unknown statement at LexToken(STRING,\"'(value)'\",line,column)"},{"fix":"Simplify the problematic index definitions in your DDL for parsing, or update to the latest version as bug fixes are frequently released for such edge cases. Report specific DDL examples as GitHub issues if the problem persists.","cause":"The parser might encounter issues with complex index definitions (e.g., multi-column indexes with many included columns) within a `CREATE TABLE` statement, causing it to skip the entire table or misparse parts of it.","error":"Table is completely missing from the parsed output, or columns are incorrect, despite valid DDL."},{"fix":"Enable strict error reporting with `DDLParser(ddl_string, silent=False)` to get a more specific `DDLParserError`. Review the DDL for syntax that might not be fully supported by `simple-ddl-parser` or dialect-specific nuances.","cause":"This generic error often occurs when the parser fails to correctly interpret a part of the DDL, leading to `None` being returned where a dictionary or list was expected, and subsequent code attempts to access it.","error":"TypeError: 'NoneType' object is not subscriptable"}]}