Skip to content

Instantly share code, notes, and snippets.

@fractaledmind
Created January 2, 2025 23:18
Show Gist options
  • Save fractaledmind/4b81f42276c49e100a3627ee9d215d79 to your computer and use it in GitHub Desktop.
Save fractaledmind/4b81f42276c49e100a3627ee9d215d79 to your computer and use it in GitHub Desktop.
Skeleton of a Ruby SQLite parser that renders the syntax diagrams for all of the statements in plain text
# ┌──────{ , }◀─────┐
# ◯─┴┬─▶[ sql-stmt ]─┬┴─▶◯
# └───────▶───────┘
def sql_stmt_list
end
# ◯─┬─────────────┬▶─────────────────────┬─┬─▶[ alter-table-stmt ]──────────▶─┬▶◯
# └─{ EXPLAIN }─┴─▶{ QUERY }─▶{ PLAN }─┘ ├─▶[ analyze-stmt ]──────────────▶─┤
# ├─▶[ attach-stmt ]───────────────▶─┤
# ├─▶[ begin-stmt ]────────────────▶─┤
# ├─▶[ commit-stmt ]───────────────▶─┤
# ├─▶[ create-index-stmt ]─────────▶─┤
# ├─▶[ create-table-stmt ]─────────▶─┤
# ├─▶[ create-trigger-stmt ]───────▶─┤
# ├─▶[ create-view-stmt ]──────────▶─┤
# ├─▶[ create-virtual-table-stmt ]─▶─┤
# ├─▶[ delete-stmt ]───────────────▶─┤
# ├─▶[ delete-stmt-limited ]───────▶─┤
# ├─▶[ detach-stmt ]───────────────▶─┤
# ├─▶[ drop-index-stmt ]───────────▶─┤
# ├─▶[ drop-table-stmt ]───────────▶─┤
# ├─▶[ drop-trigger-stmt ]─────────▶─┤
# ├─▶[ drop-view-stmt ]────────────▶─┤
# ├─▶[ insert-stmt ]───────────────▶─┤
# ├─▶[ pragma-stmt ]───────────────▶─┤
# ├─▶[ reindex-stmt ]──────────────▶─┤
# ├─▶[ release-stmt ]──────────────▶─┤
# ├─▶[ rollback-stmt ]─────────────▶─┤
# ├─▶[ savepoint-stmt ]────────────▶─┤
# ├─▶[ select-stmt ]───────────────▶─┤
# ├─▶[ update-stmt ]───────────────▶─┤
# ├─▶[ update-stmt-limited ]───────▶─┤
# └─▶[ vacuum-stmt ]───────────────▶─┘
def sql_stmt
end
# ┌────────────────────────┐
# ◯─▶─{ ALTER }─▶{ TABLE }─▶┴▶{ schema-name }─▶{ . }─┴▶{ table-name }─┐
# ┌───────────────────────────────────────────────────────────────────┘
# ├─▶{ RENAME }─▶{ TO }─▶{ new-table-name }───────────────────────────────────┬▶◯
# ├{ RENAME }─▶┬─▶{ COLUMN }─┬▶{ column-name }─▶{ TO }─▶{ new-column-name }─▶─┤
# │ └──────▶──────┘ │
# ├─▶{ ADD }─▶┬─▶{ COLUMN }─┬▶{ column-def }────────────────────────────────▶─┤
# │ └──────▶──────┘ │
# └─▶{ DROP }─▶┬─▶{ COLUMN }─┬▶{ column-name }──────────────────────────────▶─┘
# └──────▶──────┘
def alter_table_stmt
end
# ◯─▶{ ANALYZE }─▶┬────────────────────────▶───────────────────────────┬▶◯
# ├▶{ schema-name }──────────────────────────────────▶─┤
# ├▶{ index-or-table-name }──────────────────────────▶─┤
# └▶{ schema-name }─▶{ . }─▶{ table-or-index-name }──▶─┘
def analyze_stmt
end
# ◯─▶{ ATTACH }─▶┬─▶{ DATABASE }┬▶[ expr ]─▶{ AS }─▶{ schema-name }─▶◯
# └───────▶──────┘
def attach_stmt
end
# ◯─▶{ BEGIN }─▶┬─────────────────┬▶┬▶{ TRANSACTION }┬─▶◯
# ├▶{ DEFERRED }──▶─┤ └────────▶───────┘
# ├▶{ IMMEDIATE }─▶─┤
# └▶{ EXCLUSIVE }─▶─┘
def begin_stmt
end
# ◯─▶┬▶{ COMMIT }┬▶┬─{ TRANSACTION }┬─▶◯
# └▶{ END }─▶─┘ └────────▶───────┘
def commit_stmt
end
# ◯─▶{ CREATE }┬─────▶─────┬▶{ INDEX }┬▶{ IF }─▶{ NOT }─▶{ EXISTS }─┐
# └▶{ UNIQUE }┘ │ │
# ┌───────────────────────────────────┴─────────────────────────────┘
# ├─▶{ schema-name }─▶{ . }─┬▶{ index-name }─▶{ ON }─▶{ table-name }─┐
# └─────────────────────────┘ │
# ┌──────────────────────────────────────────────────────────────────┘
# └─▶{ ( }─┬▶[ indexed-column ]─┬▶{ ) }─┐
# └───────{ , }◀───────┘ │
# ┌─────◀─────────────────┤
# └─▶{ WHERE }─▶{ expr }──┴─▶─◯
def create_index_stmt
end
# ◯─▶{ CREATE }┬───────▶──────┬▶{ TABLE }┬▶{ IF }─▶{ NOT }─▶{ EXISTS }─┐
# ├▶{ TEMP }─────┤ │ │
# └▶{ TEMPORARY }┘ │ │
# ┌─────────────────────◀────────────────┴──────────────────◀──────────┘
# ├─▶{ schema-name }─▶{ . }─┬▶{ table-name }┬───────▶{ AS }─▶[ select-stmt ]───▶─────┐
# └────────▶────────────────┘ │ │
# ┌────────────────────◀────────────────────┘ ┌────────▶─────────┼▶◯
# └▶{ ( }─┬▶[ column-def ]─┬▶┬─────────────────────────────┬▶{ ) }┴▶[ table-options ]┘
# └─────{ , }◀─────┘ └[ table-constraint ]◀─{ , }◀─┘
def create_table_stmt
end
# ◯─▶{ CREATE }┬───────▶──────┬▶{ TRIGGER }┬▶{ IF }─▶{ NOT }─▶{ EXISTS }─┐
# ├▶{ TEMP }─────┤ │ │
# └▶{ TEMPORARY }┘ │ │
# ┌─────────────────────◀──────────────────┴──────────────────◀──────────┘
# ├─▶{ schema-name }─▶{ . }─┬▶{ trigger-name }┬▶{ BEFORE }──────────▶─┐
# └────────▶────────────────┘ ├▶{ AFTER }───────────▶─┤
# ├▶{ INSTEAD }─▶{ OF }─▶─┤
# ┌────────────────◀──────────────────────────┴───────◀───────────────┘
# ├▶{ DELETE }───────────────────────────────┬▶{ ON }▶{ table-name }─┐
# ├▶{ INSERT }─────────────────────────────▶─┤ │
# └▶{ UPDATE }─┬───────────────────────────▶─┤ │
# └▶{ OF }─┬▶{ column-name }─┬▶─┘ │
# └──────{ , }◀─────┘ ▼
# ┌────────────────────────◀──────┬──────────────────────────────────┘
# ├─▶{ FOR }─▶{ EACH }─▶{ ROW }─┬─┴▶{ WHEN }─▶[ expr ]─┐
# ┌───────────────────────────◀─┴──────────────────────┘
# │ ┌─────────────◀─────────────┐
# └─▶{ BEGIN }┴▶┬▶[ update-stmt ]──┬▶{ ; }┴▶{ END }─────────────────────────▶◯
# ├▶[ insert-stmt ]─▶┤
# ├▶[ delete-stmt ]─▶┤
# └▶[ select-stmt ]─▶┘
def create_trigger_stmt
end
# ◯─▶{ CREATE }┬───────▶──────┬▶{ VIEW }┬▶{ IF }─▶{ NOT }─▶{ EXISTS }─┐
# ├▶{ TEMP }─────┤ │ │
# └▶{ TEMPORARY }┘ │ │
# ┌─────────────────────◀───────────────┴──────────────────◀──────────┘
# ├─▶{ schema-name }─▶{ . }─┬▶{ view-name }─┬──────────────────────────────────┬▶{ AS }─▶[ select-stmt ]─▶◯
# └────────▶────────────────┘ └─▶{ ( }─┬▶{ column-name }─┬▶{ ) }─┘
# └──────{ , }◀─────┘
def create_view_stmt
end
# ◯─▶{ CREATE }─▶{ VIRTUAL }─▶{ TABLE }┬▶{ IF }─▶{ NOT }─▶{ EXISTS }─┐
# ┌────────────────────◀───────────────┴───────────◀─────────────────┘
# ├─▶{ schema-name }─▶{ . }─┬▶{ table-name }─┐
# └────────▶────────────────┘ │
# ┌────────────────────◀─────────────────────┘
# │ ┌─────────────────◀────────────────┐
# └─▶{ USING }─▶{ module-name }┴▶{ ( }┬▶[ module-argument ]┬▶{ ) }┴────▶◯
# └────────{ , }◀──────┘
def create_virtual_table_stmt
end
# ◯─▶┬▶{ WITH }┬───────▶──────┬─┬[ common-table-expression ]─┐
# │ └▶{ RECURSIVE }┘ └───────────{ , }◀───────────┤
# ├───────────────────────────◀───────────────────────────┘
# └─▶{ DELETE }─▶{ FROM }─▶{ qualified-table-name }─┐
# ┌──────────────────────◀──────────┘
# ├─▶{ WHERE }─▶[ expr ]─┐ ┌▶[ returning-clause ]┐
# └──────────────────────┴▶┴─────────────────────┴─▶◯
def delete_stmt
end
# ◯─▶┬▶{ WITH }┬───────▶──────┬─┬[ common-table-expression ]─┐
# │ └▶{ RECURSIVE }┘ └───────────{ , }◀───────────┤
# ├───────────────────────────◀───────────────────────────┘
# └─▶{ DELETE }─▶{ FROM }─▶[ qualified-table-name ]─┬──▶─┐
# ┌─────────────────────────◀───────────────────────┘ │
# ├─▶{ WHERE }─▶[ expr ]─┬─────────────────────────────▶─┤
# ├──────────◀───────────┘ │
# ├─▶[ returning-clause ]─┬────────────────────────────▶─┤
# ├──────────◀────────────┘ │
# ├─▶{ ORDER }─▶{ BY }┬▶[ ordering-term ]─┬────────────▶─┤
# │ └───────{ , }◀──────┤ │
# ├────────────────◀──────────────────────┘ │
# └─▶{ LIMIT }─▶[ expr ]─┬────────────────────────┬▶─────┴─▶◯
# ├─▶{ OFFSET }─▶[ expr ]─▶┤
# └─▶{ , }─▶[ expr ]─▶─────┘
def delete_stmt_limited
end
# ◯─▶{ DETACH }┬▶{ DATABASE }┬▶{ schema-name }─▶◯
# └──────▶──────┘
def detach_stmt
end
# ◯─▶{ DROP }─▶{ INDEX }┬▶{ IF }─▶{ EXISTS }┬┬▶{ schema-name }─▶{ . }┬▶{ index-name }─▶◯
# └─────────▶─────────┘└───────────▶───────────┘
def drop_index_stmt
end
# ◯─▶{ DROP }─▶{ TABLE }┬▶{ IF }─▶{ EXISTS }┬┬▶{ schema-name }─▶{ . }┬▶{ table-name }─▶◯
# └─────────▶─────────┘└───────────▶───────────┘
def drop_table_stmt
end
# ◯─▶{ DROP }─▶{ TRIGGER }┬▶{ IF }─▶{ EXISTS }┬┬▶{ schema-name }─▶{ . }┬▶{ trigger-name }─▶◯
# └─────────▶─────────┘└───────────▶───────────┘
def drop_trigger_stmt
end
# ◯─▶{ DROP }─▶{ VIEW }┬▶{ IF }─▶{ EXISTS }┬┬▶{ schema-name }─▶{ . }┬▶{ view-name }─▶◯
# └─────────▶─────────┘└───────────▶───────────┘
def drop_view_stmt
end
# ◯──┬▶{ WITH }┬───────▶───────┬─┬▶[ common-table-expression ]─┐
# ▼ └▶{ RECURSIVE }▶┘ └───────────{ , }◀────────────┤
# ├─────────────────────────◀───────────────────────────────┘
# ├─▶{ REPLACE }─────────────────────────┬─▶{ INTO }─┐
# └─▶{ INSERT }─┬───────────────────────▶┤ │
# └▶{ OR }┬─▶{ ABORT }────▶┤ │
# ├─▶{ FAIL }─────▶┤ │
# ├─▶{ IGNORE }───▶┤ │
# ├─▶{ REPLACE }──▶┤ │
# └─▶{ ROLLBACK }─▶┘ │
# ┌───────────────────◀─────┬────────────────────────┘
# └─▶{ schema-name }─▶{ . }─┴▶{ table-name }─┬▶{ AS }─▶{ alias }─┐
# ┌──────────────────────────────────────────┴───────◀───────────┘
# ├─▶{ ( }─┬▶{ column-name }─┬─▶{ ) }─┐
# │ └─────{ , }◀──────┘ │
# ├──────────────────◀────────────────┘
# ├─▶{ VALUES }┬▶{ ( }─┬▶[ expr ]─┬─▶{ ) }┬───────────────────▶┐
# │ │ └──{ , }◀──┘ ├▶[ upsert-clause ]─▶┤
# │ └──────────{ , }◀──────────┘ │
# ├─▶[ select-stmt ]──────────────────────┬───────────────────▶┤
# │ ├▶[ upsert-clause ]─▶┤
# └─▶{ DEFAULT }─▶{ VALUES }──────────────────────────────────▶┤
# ┌────────────◀──────────┤
# └─▶[ returning-clause ]─┴───▶◯
def insert_stmt
end
# ◯─▶{ PRAGMA }┬▶{ schema-name }─▶{ . }┬▶{ pragma-name }┬─────────────────────────────────┬─▶◯
# └───────────▶───────────┘ ├─▶{ = }─▶[ pragma-value ]──────▶─┤
# └─▶{ ( }─▶[ pragma-value ]─▶{ ) }─┘
def pragma_stmt
end
# ◯─▶{ REINDEX }┬─────────────────────────▶────────────────────────┬─▶◯
# ├─▶{ collation-name }────────────────────────────▶─┤
# ├─▶{ schema-name }─▶{ . }┬▶┬▶{ table-name }──────▶─┤
# └────────▶───────────────┘ └▶{ index-name }──────▶─┘
def reindex_stmt
end
# ◯─▶{ RELEASE }┬▶{ SAVEPOINT }┬▶{ savepoint-name }─▶◯
# └──────▶───────┘
def release_stmt
end
# ┌──────▶───────┐
# ◯─▶{ ROLLBACK }┬▶{ TRANSACTION }┬┬▶{ TO }┴▶{ SAVEPOINT }┴▶{ savepoint-name }┬─▶◯
# └───────▶────────┘└─────────────────────▶────────────────────┘
def rollback_stmt
end
# ◯─▶{ SAVEPOINT }─▶{ savepoint-name }─▶◯
def savepoint_stmt
end
# ◯──┬▶{ WITH }┬───────▶───────┬─┬▶[ common-table-expression ]─┐
# ▼ └▶{ RECURSIVE }▶┘ └───────────{ , }◀────────────┤
# ├─────────────────────────◀───────────────────────────────┘
# ┌──┴▶┬─────▶{ SELECT }─┬───────▶──────┬─┬▶[ result-column ]─┐
# │ │ ├▶{ DISTINCT }┤ └─────{ , }◀─────────┤
# ▲ │ └▶{ ALL }────▶┘ │
# │ │ ┌──────────────────────────◀──────────────────────┘
# │ │ ├─▶{ FROM }┬─┬▶[ table-or-subquery ]─┬─┬─▶───┐
# │ │ │ │ └────────{ , }◀─────────┘ ▲ ▼
# │ │ │ └──▶[ join-clause ]─────────┘ │
# │ │ ├──────────────────────◀─────────────────────┘
# │ │ ├─▶{ WHERE }─▶[ expr ]─┐
# │ │ ├──────────◀───────────┘
# │ │ ├────────────▶─────────────────┐
# │ │ ├─▶{ GROUP }─▶{ BY }┬▶[ expr ]┬┴▶┬─▶{ HAVING }─▶[ expr ]─┬─┐
# │ │ ▼ └──{ , }◀─┘ └────────▶──────────────┘ ▼
# │ │ ├─────────────────────────────◀────────────────────────────┘
# │ │ ├─▶{ WINDOW }┬▶{ window-name }─▶{ AS }─▶[ window-defn ]─┐
# ▲ │ │ └───────────────────{ , }◀─────────────────┤
# │ │ └──────────────────────▶─────────────────────────────▶──┤
# │ │ ┌──{ , }◀─┐ ▼
# │ └─▶{ VALUES }┬▶{ ( }─┴▶[ expr ]┴─▶{ ) }─┬─────────────────▶──┤
# │ └──────────{ , }◀──────────┘ │
# └────────────────────[ compound-operator ]◀───────────────────────┤
# ┌──────────────────◀──────────────────────────────────┘
# ├─▶{ ORDER }─▶{ BY }┬▶[ ordering-term ]─┬┐
# ▼ └───────{ , }◀──────┘│
# ├────────────────◀───────────────────────┘
# ├─▶{ LIMIT }─▶[ expr ]─▶┬───────────────────────▶─┐
# │ ├─▶{ OFFSET }─▶[ expr ]─▶─┤
# │ └─▶{ , }─▶[ expr ]──────▶─┤
# └───────────────────────────────────────────────▶─┴───────▶◯
def select_stmt
end
# ◯─▶┬▶{ WITH }┬───────▶──────┬─┬[ common-table-expression ]─┐
# │ └▶{ RECURSIVE }┘ └───────────{ , }◀───────────┤
# ├───────────────────────────◀───────────────────────────┘
# └─▶{ UPDATE }─┬───────────────────────┬▶[ qualified-table-name ]─┐
# ├▶{ OR }─▶{ ABORT }────▶┤ │
# ├▶{ OR }─▶{ FAIL }─────▶┤ │
# ├▶{ OR }─▶{ IGNORE }───▶┤ │
# ├▶{ OR }─▶{ REPLACE }──▶┤ │
# └▶{ OR }─▶{ ROLLBACK }─▶┘ │
# ┌──────────────────────────◀─────────────────────────────────────┘
# └─▶{ SET }┬┬▶{ column-name }─────┬─▶{ = }─▶[ expr ]──┐
# │└▶[ column-name-list ]┘ │
# └─────────────────{ , }◀───────────────────┤
# ┌──────────────────────────◀─────────────────────────┘
# ├─▶{ FROM }┬─┬▶[ table-or-subquery ]─┬─┬─▶───┐
# │ │ └────────{ , }◀─────────┘ │ │
# │ └──▶[ join-clause ]─────────┘ │
# ├──────────────────────◀─────────────────────┘
# ├─▶{ WHERE }─▶[ expr ]─┐ ┌▶[ returning-clause ]─┐
# └──────────────────────┴─▶─┴──────────────────────┴─▶───────────────▶◯
def update_stmt
end
# ◯─▶┬▶{ WITH }┬───────▶──────┬─┬[ common-table-expression ]─┐
# │ └▶{ RECURSIVE }┘ └───────────{ , }◀───────────┤
# ├───────────────────────────◀───────────────────────────┘
# └─▶{ UPDATE }─┬───────────────────────┬▶[ qualified-table-name ]─┐
# ├▶{ OR }─▶{ ABORT }────▶┤ │
# ├▶{ OR }─▶{ FAIL }─────▶┤ │
# ├▶{ OR }─▶{ IGNORE }───▶┤ │
# ├▶{ OR }─▶{ REPLACE }──▶┤ │
# └▶{ OR }─▶{ ROLLBACK }─▶┘ │
# ┌──────────────────────────◀─────────────────────────────────────┘
# └─▶{ SET }┬┬▶{ column-name }─────┬─▶{ = }─▶[ expr ]──┐
# │└▶[ column-name-list ]┘ │
# └─────────────────{ , }◀───────────────────┤
# ┌──────────────────────────◀─────────────────────────┘
# ├─▶{ FROM }┬─┬▶[ table-or-subquery ]─┬─┬─▶───┐
# │ │ └────────{ , }◀─────────┘ │ │
# │ └──▶[ join-clause ]─────────┘ │
# ├──────────────────────◀─────────────────────┘
# ├─▶{ WHERE }─▶[ expr ]─┐
# ├──────────◀───────────┘
# ├─▶[ returning-clause ]─┐
# ├──────────◀────────────┘
# ├─▶{ ORDER }─▶{ BY }┬▶[ ordering-term ]─┐
# │ └───────{ , }◀──────┤
# ├─────────────────◀─────────────────────┘
# ├─▶{ LIMIT }─▶[ expr ]─┬───────────────────────▶─┐
# │ ├─▶{ OFFSET }─▶[ expr ]─▶─┤
# │ └─▶{ , }─▶[ expr ]──────▶─┤
# └─────────────────────▶──────────────────────────┴─▶───────────────▶◯
def update_stmt_limited
end
# ◯─▶{ VACUUUM }┬─────────────────┬▶┬────────────────────────┬─▶◯
# └▶{ schema-name }─┘ └▶{ INTO }─▶{ filename }─┘
def vacuum_stmt
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment