poached
SQL parsing tools for building IDEs, editors, and query analyzers.
A DuckDB extension exposing SQL parsing functionality for building IDEs, syntax highlighters, query analyzers, and developer tools. Uses DuckDB's internal parser for accurate results.
Installation
INSTALL poached FROM community;
LOAD poached;
Syntax Validation
Check if SQL is syntactically valid
SELECT is_valid_sql('SELECT * FROM users WHERE id = 1'); -- true
SELECT is_valid_sql('SELECT * FROM'); -- false
Get error message for invalid SQL
SELECT sql_error_message('SELECT * FROM');
-- 'Parser Error: syntax error at or near ";"'
Tokenization
Returns tokens with byte positions and categories for syntax highlighting:
SELECT * FROM tokenize_sql('SELECT * FROM users');
┌───────────────┬──────────────────┐
│ byte_position │ category │
├───────────────┼──────────────────┤
│ 0 │ KEYWORD │
│ 7 │ OPERATOR │
│ 9 │ KEYWORD │
│ 14 │ IDENTIFIER │
└───────────────┴──────────────────┘
Categories: KEYWORD, IDENTIFIER, OPERATOR, NUMERIC_CONSTANT, STRING_CONSTANT
Statement Analysis
Parse multi-statement SQL
SELECT * FROM parse_statements('SELECT 1; CREATE TABLE t(x INT)');
┌────────────┬───────────┬───────┬─────────────┐
│ stmt_index │ stmt_type │ error │ param_count │
├────────────┼───────────┼───────┼─────────────┤
│ 0 │ SELECT │ NULL │ 0 │
│ 1 │ CREATE │ NULL │ 0 │
└────────────┴───────────┴───────┴─────────────┘
Count statements
SELECT num_statements('SELECT 1; SELECT 2; SELECT 3'); -- 3
Query Introspection
Extract column names from SELECT
SELECT * FROM parse_columns('SELECT id, name AS username FROM users', 0);
┌───────────┬──────────┐
│ col_index │ col_name │
├───────────┼──────────┤
│ 0 │ id │
│ 1 │ username │
└───────────┴──────────┘
Extract table references
SELECT * FROM parse_tables('SELECT * FROM users JOIN orders ON true');
┌─────────────┬────────────┬─────────┐
│ schema_name │ table_name │ context │
├─────────────┼────────────┼─────────┤
│ NULL │ users │ FROM │
│ NULL │ orders │ JOIN │
└─────────────┴────────────┴─────────┘
Get table names as array
SELECT parse_table_names('SELECT * FROM a JOIN b ON true'); -- [a, b]
Extract function calls
SELECT * FROM parse_functions('SELECT COUNT(*), UPPER(name) FROM t');
┌───────────────┬───────────────┐
│ function_name │ function_type │
├───────────────┼───────────────┤
│ count_star │ aggregate │
│ upper │ scalar │
└───────────────┴───────────────┘
Utilities
List all SQL keywords
SELECT * FROM sql_keywords() LIMIT 5;
Check if string is a keyword
SELECT is_keyword('SELECT'); -- true
SELECT is_keyword('mytable'); -- false
Strip comments from SQL
SELECT sql_strip_comments('SELECT 1 -- comment'); -- 'SELECT 1 '
Get parse info as JSON
SELECT sql_parse_json('SELECT 1 + 2 AS result');
Use Cases
- SQL IDEs: Syntax highlighting, real-time validation
- Query analyzers: Extract table/function dependencies
- Security auditing: Analyze WHERE clauses and access patterns
- Documentation: Auto-generate column lists from queries