sql-parser-cst
Advanced tools
Comparing version 0.1.2 to 0.2.0
@@ -57,11 +57,11 @@ "use strict"; | ||
program: (node) => node.statements.map(layout), | ||
empty_statement: () => "", | ||
empty_stmt: () => "", | ||
// SELECT statement | ||
select_statement: (node) => node.clauses.map(layout), | ||
select_stmt: (node) => node.clauses.map(layout), | ||
// SELECT | ||
select_clause: (node) => [ | ||
line(layout(node.selectKw)), | ||
indent(...node.columns | ||
indent(...node.columns.items | ||
.map(layout) | ||
.map((col, i) => i < node.columns.length - 1 ? line(col, ",") : line(col))), | ||
.map((col, i) => i < node.columns.items.length - 1 ? line(col, ",") : line(col))), | ||
], | ||
@@ -91,3 +91,3 @@ // FROM | ||
number: (node) => node.text, | ||
bool: (node) => node.text, | ||
boolean: (node) => node.text, | ||
null: (node) => node.text, | ||
@@ -94,0 +94,0 @@ }); |
@@ -5,2 +5,4 @@ import { Node, ParserOptions, Program } from "./sql"; | ||
export { format } from "./format/format"; | ||
export * from "./cstVisitor"; | ||
export * from "./cstTransformer"; | ||
export declare type DialectFn = (str: string, options: ParserOptions) => Program; | ||
@@ -7,0 +9,0 @@ export declare type DialectOption = { |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -11,2 +25,4 @@ exports.show = exports.parse = exports.format = exports.sqlite = exports.mysql = void 0; | ||
Object.defineProperty(exports, "format", { enumerable: true, get: function () { return format_1.format; } }); | ||
__exportStar(require("./cstVisitor"), exports); | ||
__exportStar(require("./cstTransformer"), exports); | ||
function parse(sql, options) { | ||
@@ -13,0 +29,0 @@ return options.dialect(sql, options); |
139
lib/show.js
@@ -34,12 +34,11 @@ "use strict"; | ||
program: (node) => show(node.statements, ";"), | ||
empty_statement: () => "", | ||
empty_stmt: () => "", | ||
// SELECT statement | ||
compound_select_statement: (node) => show([node.left, node.operator, node.right]), | ||
select_statement: (node) => show(node.clauses), | ||
compound_select_stmt: (node) => show([node.left, node.operator, node.right]), | ||
select_stmt: (node) => show(node.clauses), | ||
// WITH | ||
with_clause: (node) => show([node.withKw, node.recursiveKw, show(node.tables, ",")]), | ||
with_clause: (node) => show([node.withKw, node.recursiveKw, node.tables]), | ||
common_table_expression: (node) => show([node.table, node.columns, node.asKw, node.optionKw, node.expr]), | ||
// SELECT | ||
select_clause: (node) => show([node.selectKw, node.options.length > 0 ? node.options : undefined]) + | ||
show(node.columns, ","), | ||
select_clause: (node) => show([node.selectKw, node.options, node.columns]), | ||
// FROM | ||
@@ -50,9 +49,9 @@ from_clause: (node) => show([node.fromKw, node.tables]), | ||
join_using_specification: (node) => show([node.usingKw, node.expr]), | ||
sort_specification: (node) => show([node.expr, node.orderKw]), | ||
sort_specification: (node) => show([node.expr, node.orderKw, node.nullHandlingKw]), | ||
// WHERE .. GROUP BY .. HAVING .. ORDER BY .. PARTITION BY | ||
where_clause: (node) => show([node.whereKw, node.expr]), | ||
group_by_clause: (node) => show(node.groupByKw) + show(node.columns, ","), | ||
group_by_clause: (node) => show([node.groupByKw, node.columns]), | ||
having_clause: (node) => show([node.havingKw, node.expr]), | ||
order_by_clause: (node) => show(node.orderByKw) + show(node.specifications, ","), | ||
partition_by_clause: (node) => show(node.partitionByKw) + show(node.specifications, ","), | ||
order_by_clause: (node) => show([node.orderByKw, node.specifications, node.withRollupKw]), | ||
partition_by_clause: (node) => show([node.partitionByKw, node.specifications]), | ||
// WINDOW | ||
@@ -85,3 +84,3 @@ window_clause: (node) => show(node.windowKw) + show(node.namedWindows, ","), | ||
// CREATE TABLE statement | ||
create_table_statement: (node) => show([ | ||
create_table_stmt: (node) => show([ | ||
node.createKw, | ||
@@ -93,2 +92,3 @@ node.temporaryKw, | ||
node.columns, | ||
node.options, | ||
]), | ||
@@ -105,7 +105,7 @@ column_definition: (node) => show([ | ||
constraint_null: (node) => show(node.nullKw), | ||
constraint_not_null: (node) => show(node.notNullKw), | ||
constraint_not_null: (node) => show([node.notNullKw, node.onConflict]), | ||
constraint_auto_increment: (node) => show(node.autoIncrementKw), | ||
constraint_default: (node) => show([node.defaultKw, node.expr]), | ||
constraint_comment: (node) => show([node.commentKw, node.value]), | ||
constraint_primary_key: (node) => show([node.primaryKeyKw, node.columns]), | ||
constraint_primary_key: (node) => show([node.primaryKeyKw, node.columns, node.onConflict]), | ||
constraint_foreign_key: (node) => show([node.foreignKeyKw, node.columns, node.references]), | ||
@@ -115,4 +115,4 @@ references_specification: (node) => show([node.referencesKw, node.table, node.columns, node.options]), | ||
referential_match: (node) => show([node.matchKw, node.typeKw]), | ||
constraint_unique: (node) => show([node.uniqueKw, node.columns]), | ||
constraint_check: (node) => show([node.checkKw, node.expr]), | ||
constraint_unique: (node) => show([node.uniqueKw, node.columns, node.onConflict]), | ||
constraint_check: (node) => show([node.checkKw, node.expr, node.onConflict]), | ||
constraint_index: (node) => show([node.indexTypeKw, node.indexKw, node.columns]), | ||
@@ -125,4 +125,13 @@ constraint_generated: (node) => show([node.generatedKw, node.asKw, node.expr, node.storageKw]), | ||
constraint_engine_attribute: (node) => show([node.engineAttributeKw, node.hasEq ? "=" : undefined, node.value]), | ||
on_conflict_clause: (node) => show([node.onConflictKw, node.resolutionKw]), | ||
// options | ||
table_option: (node) => show([node.name, node.hasEq ? "=" : undefined, node.value]), | ||
// ALTER TABLE statement | ||
alter_table_stmt: (node) => show([node.alterTableKw, node.table, node.actions]), | ||
alter_rename_table: (node) => show([node.renameKw, node.newName]), | ||
alter_rename_column: (node) => show([node.renameKw, node.oldName, node.toKw, node.newName]), | ||
alter_add_column: (node) => show([node.addKw, node.column]), | ||
alter_drop_column: (node) => show([node.dropKw, node.column]), | ||
// DROP TABLE statement | ||
drop_table_statement: (node) => show([ | ||
drop_table_stmt: (node) => show([ | ||
node.dropKw, | ||
@@ -132,7 +141,7 @@ node.temporaryKw, | ||
node.ifExistsKw, | ||
show(node.tables, ","), | ||
node.tables, | ||
node.behaviorKw, | ||
]), | ||
// INSERT INTO statement | ||
insert_statement: (node) => show([ | ||
insert_stmt: (node) => show([ | ||
node.insertKw, | ||
@@ -149,7 +158,7 @@ node.options, | ||
// UPDATE statement | ||
update_statement: (node) => show([ | ||
update_stmt: (node) => show([ | ||
node.updateKw, | ||
show(node.tables, ","), | ||
node.tables, | ||
node.setKw, | ||
show(node.assignments, ","), | ||
node.assignments, | ||
node.where, | ||
@@ -159,3 +168,81 @@ ]), | ||
// DELETE FROM statement | ||
delete_statement: (node) => show([node.deleteKw, node.fromKw, node.table, node.where]), | ||
delete_stmt: (node) => show([node.deleteKw, node.fromKw, node.table, node.where]), | ||
// CREATE VIEW statement | ||
create_view_stmt: (node) => show([ | ||
node.createKw, | ||
node.temporaryKw, | ||
node.viewKw, | ||
node.ifNotExistsKw, | ||
node.name, | ||
node.columns, | ||
node.asKw, | ||
node.expr, | ||
]), | ||
// DROP VIEW statement | ||
drop_view_stmt: (node) => show([node.dropViewKw, node.ifExistsKw, node.views, node.behaviorKw]), | ||
// CREATE INDEX statement | ||
create_index_stmt: (node) => show([ | ||
node.createKw, | ||
node.indexTypeKw, | ||
node.indexKw, | ||
node.ifNotExistsKw, | ||
node.name, | ||
node.onKw, | ||
node.table, | ||
node.columns, | ||
node.where, | ||
]), | ||
// DROP INDEX | ||
drop_index_stmt: (node) => show([ | ||
node.dropIndexKw, | ||
node.ifExistsKw, | ||
node.indexes, | ||
node.onKw, | ||
node.table, | ||
]), | ||
// CREATE TRIGGER statement | ||
create_trigger_stmt: (node) => show([ | ||
node.createKw, | ||
node.temporaryKw, | ||
node.triggerKw, | ||
node.ifNotExistsKw, | ||
node.name, | ||
node.event, | ||
node.onKw, | ||
node.table, | ||
node.forEachRowKw, | ||
node.condition, | ||
node.body, | ||
]), | ||
trigger_event: (node) => show([node.timeKw, node.eventKw, node.ofKw, node.columns]), | ||
trigger_condition: (node) => show([node.whenKw, node.expr]), | ||
trigger_body: (node) => show([node.beginKw, show(node.statements, ";"), ";", node.endKw]), | ||
// DROP TRIGGER | ||
drop_trigger_stmt: (node) => show([node.dropTriggerKw, node.ifExistsKw, node.trigger]), | ||
// ANALYZE statement | ||
analyze_stmt: (node) => show([node.analyzeKw, node.tableKw, node.tables]), | ||
// EXPLAIN statement | ||
explain_stmt: (node) => show([node.explainKw, node.analyzeKw, node.queryPlanKw, node.statement]), | ||
// Transactions | ||
start_transaction_stmt: (node) => show([node.startKw, node.behaviorKw, node.transactionKw]), | ||
commit_transaction_stmt: (node) => show([node.commitKw, node.transactionKw]), | ||
rollback_transaction_stmt: (node) => show([node.rollbackKw, node.transactionKw, node.savepoint]), | ||
rollback_to_savepoint: (node) => show([node.toKw, node.savepointKw, node.savepoint]), | ||
savepoint_stmt: (node) => show([node.savepointKw, node.savepoint]), | ||
release_savepoint_stmt: (node) => show([node.releaseKw, node.savepointKw, node.savepoint]), | ||
// SQLite-specific statements | ||
attach_database_stmt: (node) => show([node.attachKw, node.databaseKw, node.file, node.asKw, node.schema]), | ||
detach_database_stmt: (node) => show([node.detachKw, node.databaseKw, node.schema]), | ||
vacuum_stmt: (node) => show([node.vacuumKw, node.schema, node.intoKw, node.file]), | ||
reindex_stmt: (node) => show([node.reindexKw, node.table]), | ||
pragma_stmt: (node) => show([node.pragmaKw, node.pragma]), | ||
pragma_assignment: (node) => show([node.name, "=", node.value]), | ||
pragma_func_call: (node) => show([node.name, node.args]), | ||
create_virtual_table_stmt: (node) => show([ | ||
node.createVirtualTableKw, | ||
node.ifNotExistsKw, | ||
node.table, | ||
node.usingKw, | ||
node.module, | ||
]), | ||
// Expressions | ||
@@ -165,7 +252,9 @@ expr_list: (node) => show(node.items, ","), | ||
binary_expr: (node) => show([node.left, node.operator, node.right]), | ||
unary_expr: (node) => show([node.operator, node.expr]), | ||
func_call: (node) => show(node.name) + show(node.args) + (node.over ? show(node.over) : ""), | ||
prefix_op_expr: (node) => show([node.operator, node.expr]), | ||
postfix_op_expr: (node) => show([node.expr, node.operator]), | ||
func_call: (node) => show([node.name, node.args, node.filter, node.over]), | ||
distinct_arg: (node) => show([node.distinctKw, node.value]), | ||
cast_expr: (node) => show([node.castKw, node.args]), | ||
cast_arg: (node) => show([node.expr, node.asKw, node.dataType]), | ||
filter_arg: (node) => show([node.filterKw, node.where]), | ||
over_arg: (node) => show([node.overKw, node.window]), | ||
@@ -191,5 +280,5 @@ between_expr: (node) => show([node.left, node.betweenKw, node.begin, node.andKw, node.end]), | ||
number: (node) => node.text, | ||
bool: (node) => node.text, | ||
boolean: (node) => node.text, | ||
null: (node) => node.text, | ||
// Cast to FullTransformMap, so TypeScript ensures all node types are covered | ||
}); |
404
lib/sql.d.ts
@@ -31,3 +31,10 @@ type BaseNode = { | ||
| ReferentialMatch | ||
| OnConflictClause | ||
| TableOption | ||
| AlterAction | ||
| TriggerEvent | ||
| TriggerCondition | ||
| TriggerBody | ||
| AllColumns | ||
| RollbackToSavepoint | ||
| DistinctArg | ||
@@ -39,2 +46,3 @@ | CastArg | ||
| WindowDefinition | ||
| FilterArg | ||
| OverArg | ||
@@ -48,3 +56,5 @@ | FrameNode | ||
| ColumnAssignment | ||
| Alias; | ||
| Alias | ||
| PragmaAssignment | ||
| PragmaFuncCall; | ||
@@ -57,10 +67,21 @@ type Program = BaseNode & { | ||
type Statement = | ||
| EmptyStatement | ||
| CompoundSelectStatement | ||
| SelectStatement | ||
| CreateTableStatement | ||
| DropTableStatement | ||
| InsertStatement | ||
| DeleteStatement | ||
| UpdateStatement; | ||
| EmptyStmt | ||
| CompoundSelectStmt | ||
| SelectStmt | ||
| CreateTableStmt | ||
| AlterTableStmt | ||
| DropTableStmt | ||
| InsertStmt | ||
| DeleteStmt | ||
| UpdateStmt | ||
| CreateViewStmt | ||
| DropViewStmt | ||
| CreateIndexStmt | ||
| DropIndexStmt | ||
| CreateTriggerStmt | ||
| DropTriggerStmt | ||
| AnalyzeStmt | ||
| ExplainStmt | ||
| TransactionStmt | ||
| SqliteStmt; | ||
@@ -71,3 +92,4 @@ type Expr = | ||
| BinaryExpr | ||
| UnaryExpr | ||
| PrefixOpExpr | ||
| PostfixOpExpr | ||
| FuncCall | ||
@@ -87,8 +109,8 @@ | CastExpr | ||
| NumberLiteral | ||
| BoolLiteral | ||
| BooleanLiteral | ||
| NullLiteral | ||
| DateTimeLiteral; | ||
type EmptyStatement = BaseNode & { | ||
type: "empty_statement"; | ||
type EmptyStmt = BaseNode & { | ||
type: "empty_stmt"; | ||
foo: number; | ||
@@ -98,4 +120,4 @@ }; | ||
// SELECT | ||
type CompoundSelectStatement = BaseNode & { | ||
type: "compound_select_statement"; | ||
type CompoundSelectStmt = BaseNode & { | ||
type: "compound_select_stmt"; | ||
left: SubSelect; | ||
@@ -106,9 +128,6 @@ operator: Keyword | Keyword[]; // { UNION | EXCEPT | INTERSECT } [ALL | DISTINCT] | ||
type SubSelect = | ||
| SelectStatement | ||
| CompoundSelectStatement | ||
| ParenExpr<SubSelect>; | ||
type SubSelect = SelectStmt | CompoundSelectStmt | ParenExpr<SubSelect>; | ||
type SelectStatement = BaseNode & { | ||
type: "select_statement"; | ||
type SelectStmt = BaseNode & { | ||
type: "select_stmt"; | ||
clauses: Clause[]; | ||
@@ -134,3 +153,3 @@ }; | ||
recursiveKw?: Keyword; | ||
tables: CommonTableExpression[]; | ||
tables: ExprList<CommonTableExpression>; | ||
}; | ||
@@ -151,3 +170,3 @@ | ||
options: Keyword[]; | ||
columns: (Expr | Alias<Expr>)[]; | ||
columns: ExprList<Expr | Alias<Expr>>; | ||
}; | ||
@@ -170,3 +189,3 @@ | ||
groupByKw: Keyword[]; | ||
columns: Expr[]; | ||
columns: ExprList<Expr>; | ||
}; | ||
@@ -204,3 +223,4 @@ | ||
orderByKw: Keyword[]; | ||
specifications: Expr[]; | ||
specifications: ExprList<SortSpecification>; | ||
withRollupKw?: Keyword[]; // WITH ROLLUP | ||
}; | ||
@@ -211,3 +231,3 @@ | ||
partitionByKw: Keyword[]; | ||
specifications: Expr[]; | ||
specifications: ExprList<Expr>; | ||
}; | ||
@@ -247,8 +267,9 @@ | ||
expr: Expr; | ||
orderKw?: Keyword; | ||
orderKw?: Keyword; // ASC | DESC | ||
nullHandlingKw?: Keyword[]; // NULLS FIRST | NULLS LAST | ||
}; | ||
// CREATE TABLE | ||
type CreateTableStatement = BaseNode & { | ||
type: "create_table_statement"; | ||
type CreateTableStmt = BaseNode & { | ||
type: "create_table_stmt"; | ||
createKw: Keyword; | ||
@@ -262,2 +283,3 @@ tableKw: Keyword; | ||
>; | ||
options?: ExprList<TableOption>; | ||
}; | ||
@@ -326,2 +348,3 @@ | ||
columns?: ParenExpr<ExprList<ColumnRef>>; | ||
onConflict?: OnConflictClause; | ||
}; | ||
@@ -361,2 +384,3 @@ | ||
columns?: ParenExpr<ExprList<ColumnRef>>; | ||
onConflict?: OnConflictClause; | ||
}; | ||
@@ -368,2 +392,3 @@ | ||
expr: ParenExpr<Expr>; | ||
onConflict?: OnConflictClause; | ||
}; | ||
@@ -386,2 +411,3 @@ | ||
notNullKw: Keyword[]; | ||
onConflict?: OnConflictClause; | ||
}; | ||
@@ -444,5 +470,58 @@ | ||
type OnConflictClause = BaseNode & { | ||
type: "on_conflict_clause"; | ||
onConflictKw: Keyword[]; // ON CONFLICT | ||
resolutionKw: Keyword; // ROLLBACK | ABORT | FAIL | IGNORE | REPLACE | ||
}; | ||
type TableOption = BaseNode & { | ||
type: "table_option"; | ||
name: Keyword | Keyword[]; | ||
hasEq?: boolean; // True when "=" sign is used | ||
value?: NumberLiteral | StringLiteral | Identifier | Keyword; | ||
}; | ||
// ALTER TABLE | ||
type AlterTableStmt = BaseNode & { | ||
type: "alter_table_stmt"; | ||
alterTableKw: Keyword[]; | ||
table: TableRef; | ||
actions: ExprList<AlterAction>; | ||
}; | ||
type AlterAction = | ||
| AlterRenameTable | ||
| AlterRenameColumn | ||
| AlterAddColumn | ||
| AlterDropColumn; | ||
type AlterRenameTable = BaseNode & { | ||
type: "alter_rename_table"; | ||
renameKw: Keyword | Keyword[]; // RENAME | RENAME TO | RENAME AS | ||
newName: TableRef; | ||
}; | ||
type AlterRenameColumn = BaseNode & { | ||
type: "alter_rename_column"; | ||
renameKw: Keyword | Keyword[]; // RENAME | RENAME COLUMN | ||
oldName: ColumnRef; | ||
toKw: Keyword; // TO | AS | ||
newName: ColumnRef; | ||
}; | ||
type AlterAddColumn = BaseNode & { | ||
type: "alter_add_column"; | ||
addKw: Keyword | Keyword[]; // ADD | ADD COLUMN | ||
column: ColumnDefinition; | ||
}; | ||
type AlterDropColumn = BaseNode & { | ||
type: "alter_drop_column"; | ||
dropKw: Keyword | Keyword[]; // DROP | DROP COLUMN | ||
column: ColumnRef; | ||
}; | ||
// DROP TABLE | ||
type DropTableStatement = BaseNode & { | ||
type: "drop_table_statement"; | ||
type DropTableStmt = BaseNode & { | ||
type: "drop_table_stmt"; | ||
dropKw: Keyword; | ||
@@ -452,3 +531,3 @@ temporaryKw?: Keyword; | ||
ifExistsKw?: Keyword[]; | ||
tables: TableRef[]; | ||
tables: ExprList<TableRef>; | ||
behaviorKw?: Keyword; // CASCADE | RESTRICT | ||
@@ -458,4 +537,4 @@ }; | ||
// INSERT INTO | ||
type InsertStatement = BaseNode & { | ||
type: "insert_statement"; | ||
type InsertStmt = BaseNode & { | ||
type: "insert_stmt"; | ||
insertKw: Keyword; // INSERT | REPLACE | ||
@@ -491,4 +570,4 @@ options: InsertOption[]; | ||
// DELETE FROM | ||
type DeleteStatement = BaseNode & { | ||
type: "delete_statement"; | ||
type DeleteStmt = BaseNode & { | ||
type: "delete_stmt"; | ||
deleteKw: Keyword; | ||
@@ -501,8 +580,8 @@ fromKw: Keyword; | ||
// UPDATE | ||
type UpdateStatement = BaseNode & { | ||
type: "update_statement"; | ||
type UpdateStmt = BaseNode & { | ||
type: "update_stmt"; | ||
updateKw: Keyword; | ||
tables: TableRef[]; | ||
tables: ExprList<TableRef>; | ||
setKw: Keyword; | ||
assignments: ColumnAssignment[]; | ||
assignments: ExprList<ColumnAssignment>; | ||
where?: WhereClause; | ||
@@ -517,2 +596,224 @@ }; | ||
// CREATE VIEW | ||
type CreateViewStmt = BaseNode & { | ||
type: "create_view_stmt"; | ||
createKw: Keyword; | ||
temporaryKw?: Keyword; | ||
viewKw: Keyword; | ||
ifNotExistsKw?: Keyword[]; | ||
name: TableRef; | ||
columns?: ParenExpr<ExprList<ColumnRef>>; | ||
asKw: Keyword; | ||
expr: SubSelect; | ||
}; | ||
// DROP VIEW | ||
type DropViewStmt = BaseNode & { | ||
type: "drop_view_stmt"; | ||
dropViewKw: Keyword[]; | ||
ifExistsKw?: Keyword[]; | ||
views: ExprList<TableRef>; | ||
behaviorKw?: Keyword; // CASCADE | RESTRICT | ||
}; | ||
// CREATE INDEX | ||
type CreateIndexStmt = BaseNode & { | ||
type: "create_index_stmt"; | ||
createKw: Keyword; // CREATE | ||
indexTypeKw?: Keyword; // UNIQUE | FULLTEXT | SPATIAL | ||
indexKw: Keyword; // INDEX | ||
ifNotExistsKw?: Keyword[]; // IF NOT EXISTS | ||
name: TableRef; | ||
onKw: Keyword; // ON | ||
table: TableRef; | ||
columns: ParenExpr<ExprList<ColumnRef>>; | ||
where?: WhereClause; | ||
}; | ||
// DROP INDEX | ||
type DropIndexStmt = BaseNode & { | ||
type: "drop_index_stmt"; | ||
dropIndexKw: Keyword[]; // DROP INDEX | ||
ifExistsKw?: Keyword[]; // IF EXISTS | ||
indexes: ExprList<TableRef>; | ||
onKw?: Keyword; // ON | ||
table?: TableRef; | ||
}; | ||
// CREATE TRIGGER | ||
type CreateTriggerStmt = BaseNode & { | ||
type: "create_trigger_stmt"; | ||
createKw: Keyword; // CREATE | ||
temporaryKw?: Keyword; // TEMPORARY | TEMP | ||
triggerKw: Keyword; // TRIGGER | ||
ifNotExistsKw?: Keyword[]; // IF NOT EXISTS | ||
name: TableRef; | ||
event: TriggerEvent; | ||
onKw: Keyword; // ON | ||
table: TableRef; | ||
forEachRowKw?: Keyword[]; // FOR EACH ROW | ||
condition?: TriggerCondition; | ||
body: TriggerBody; | ||
}; | ||
type TriggerEvent = BaseNode & { | ||
type: "trigger_event"; | ||
timeKw?: Keyword | Keyword[]; // BEFORE | AFTER | INSTEAD OF | ||
eventKw: Keyword; // INSERT | DELETE | UPDATE | ||
ofKw?: Keyword; // OF | ||
columns?: ExprList<ColumnRef>; | ||
}; | ||
type TriggerCondition = BaseNode & { | ||
type: "trigger_condition"; | ||
whenKw?: Keyword; // WHEN | ||
expr: Expr; | ||
}; | ||
type TriggerBody = BaseNode & { | ||
type: "trigger_body"; | ||
beginKw: Keyword; // BEGIN | ||
statements: Statement[]; | ||
endKw: Keyword; // END | ||
}; | ||
// DROP TRIGGER | ||
type DropTriggerStmt = BaseNode & { | ||
type: "drop_trigger_stmt"; | ||
dropTriggerKw: Keyword[]; // DROP TRIGGER | ||
ifExistsKw?: Keyword[]; // IF EXISTS | ||
trigger: TableRef; | ||
}; | ||
// ANALYZE | ||
type AnalyzeStmt = BaseNode & { | ||
type: "analyze_stmt"; | ||
analyzeKw: Keyword; // ANALYZE | ||
tableKw?: Keyword; // TABLE | ||
tables: ExprList<TableRef>; | ||
}; | ||
// EXPLAIN | ||
type ExplainStmt = BaseNode & { | ||
type: "explain_stmt"; | ||
explainKw: Keyword; // EXPLAIN | DESCRIBE | DESC | ||
analyzeKw?: Keyword; // ANALYZE | ||
queryPlanKw?: Keyword[]; // QUERY PLAN | ||
statement: Statement; | ||
}; | ||
// Transactions | ||
type TransactionStmt = | ||
| StartTransactionStmt | ||
| CommitTransactionStmt | ||
| RollbackTransactionStmt | ||
| SavepointStmt | ||
| ReleaseSavepointStmt; | ||
type StartTransactionStmt = BaseNode & { | ||
type: "start_transaction_stmt"; | ||
startKw: Keyword; // START | BEGIN | ||
behaviorKw?: Keyword; // DEFERRED | IMMEDIATE | EXCLUSIVE | ||
transactionKw?: Keyword; // TRANSACTION | WORK | ||
}; | ||
type CommitTransactionStmt = BaseNode & { | ||
type: "commit_transaction_stmt"; | ||
commitKw: Keyword; // COMMIT | END | ||
transactionKw?: Keyword; // TRANSACTION | WORK | ||
}; | ||
type RollbackTransactionStmt = BaseNode & { | ||
type: "rollback_transaction_stmt"; | ||
rollbackKw: Keyword; // ROLLBACK | ||
transactionKw?: Keyword; // TRANSACTION | WORK | ||
savepoint?: RollbackToSavepoint; | ||
}; | ||
type RollbackToSavepoint = BaseNode & { | ||
type: "rollback_to_savepoint"; | ||
toKw: Keyword; // TO | ||
savepointKw?: Keyword; // SAVEPOINT | ||
savepoint: Identifier; | ||
}; | ||
type SavepointStmt = BaseNode & { | ||
type: "savepoint_stmt"; | ||
savepointKw: Keyword; // SAVEPOINT | ||
savepoint: Identifier; | ||
}; | ||
type ReleaseSavepointStmt = BaseNode & { | ||
type: "release_savepoint_stmt"; | ||
releaseKw: Keyword; // RELEASE | ||
savepointKw?: Keyword; // SAVEPOINT | ||
savepoint: Identifier; | ||
}; | ||
// SQLite-specific statements | ||
type SqliteStmt = | ||
| AttachDatabaseStmt | ||
| DetachDatabaseStmt | ||
| VacuumStmt | ||
| ReindexStmt | ||
| PragmaStmt | ||
| CreateVirtualTableStmt; | ||
type AttachDatabaseStmt = BaseNode & { | ||
type: "attach_database_stmt"; | ||
attachKw: Keyword; // ATTACH | ||
databaseKw?: Keyword; // DATABASE | ||
file: Expr; | ||
asKw: Keyword; // AS | ||
schema: Identifier; | ||
}; | ||
type DetachDatabaseStmt = BaseNode & { | ||
type: "detach_database_stmt"; | ||
detachKw: Keyword; // DETACH | ||
databaseKw?: Keyword; // DATABASE | ||
schema: Identifier; | ||
}; | ||
type VacuumStmt = BaseNode & { | ||
type: "vacuum_stmt"; | ||
vacuumKw: Keyword; // VACUUM | ||
schema?: Identifier; | ||
intoKw?: Keyword; // INTO | ||
file?: StringLiteral; | ||
}; | ||
type ReindexStmt = BaseNode & { | ||
type: "reindex_stmt"; | ||
reindexKw: Keyword; // REINDEX | ||
table?: TableRef; | ||
}; | ||
type PragmaStmt = BaseNode & { | ||
type: "pragma_stmt"; | ||
pragmaKw: Keyword; // PRAGMA | ||
pragma: TableRef | PragmaAssignment | PragmaFuncCall; | ||
}; | ||
type PragmaAssignment = BaseNode & { | ||
type: "pragma_assignment"; | ||
name: TableRef; | ||
value: Literal | Keyword; | ||
}; | ||
type PragmaFuncCall = BaseNode & { | ||
type: "pragma_func_call"; | ||
name: TableRef; | ||
args: ParenExpr<Literal | Keyword>; | ||
}; | ||
type CreateVirtualTableStmt = BaseNode & { | ||
type: "create_virtual_table_stmt"; | ||
createVirtualTableKw: Keyword[]; // CREATE VIRTUAL TABLE | ||
ifNotExistsKw?: Keyword[]; // IF NOT EXISTS | ||
table: TableRef; | ||
usingKw: Keyword; // USING | ||
module: FuncCall; | ||
}; | ||
// Window frame | ||
@@ -600,4 +901,4 @@ type FrameNode = | ||
type UnaryExpr = BaseNode & { | ||
type: "unary_expr"; | ||
type PrefixOpExpr = BaseNode & { | ||
type: "prefix_op_expr"; | ||
operator: string | Keyword[]; | ||
@@ -607,9 +908,22 @@ expr: Expr; | ||
type PostfixOpExpr = BaseNode & { | ||
type: "postfix_op_expr"; | ||
operator: string | Keyword[]; | ||
expr: Expr; | ||
}; | ||
type FuncCall = BaseNode & { | ||
type: "func_call"; | ||
name: Identifier; | ||
args: ParenExpr<ExprList<Expr | AllColumns | DistinctArg>>; | ||
args?: ParenExpr<ExprList<Expr | AllColumns | DistinctArg>>; | ||
filter?: FilterArg; | ||
over?: OverArg; | ||
}; | ||
type FilterArg = BaseNode & { | ||
type: "filter_arg"; | ||
filterKw: Keyword; // FILTER | ||
where: ParenExpr<WhereClause>; | ||
}; | ||
type OverArg = BaseNode & { | ||
@@ -694,4 +1008,4 @@ type: "over_arg"; | ||
type BoolLiteral = BaseNode & { | ||
type: "bool"; | ||
type BooleanLiteral = BaseNode & { | ||
type: "boolean"; | ||
text: string; | ||
@@ -698,0 +1012,0 @@ }; |
@@ -5,3 +5,3 @@ { | ||
"license": "GPL-2.0-or-later", | ||
"version": "0.1.2", | ||
"version": "0.2.0", | ||
"main": "lib/parser.js", | ||
@@ -18,3 +18,3 @@ "types": "lib/parser.d.ts", | ||
"lib/", | ||
"pegjs/" | ||
"AUTHORS" | ||
], | ||
@@ -44,4 +44,4 @@ "scripts": { | ||
"watch": { | ||
"generate": "pegjs/sql.pegjs" | ||
"generate": "src/sql.pegjs" | ||
} | ||
} |
@@ -9,2 +9,7 @@ # SQL Parser CST [![npm version](https://img.shields.io/npm/v/sql-parser-cst)](https://www.npmjs.com/package/sql-parser-cst) ![example workflow](https://github.com/nene/sql-parser-cst/actions/workflows/build.yml/badge.svg) | ||
For now it supports the following SQL dialects: | ||
- **SQLite** - supports all SQLite statements (but some parts of syntax are still unsupported). | ||
- **MySQL** - basic support for the most common SQL statements. | ||
**Note:** This is pre-alpha quality software in early development stages. | ||
@@ -15,5 +20,5 @@ | ||
```ts | ||
import { parse, show, sqlite } from "sql-parser-cst"; | ||
import { parse, show, sqlite, cstVisitor } from "sql-parser-cst"; | ||
const cst = parse("SELECT * FROM my_table", { | ||
const cst = parse("select * from my_table", { | ||
dialect: sqlite, | ||
@@ -27,7 +32,12 @@ // These are optional: | ||
// Change table name | ||
cst.statements[0].clauses[1].tables[0].table.text = "your_table"; | ||
// convert all keywords to uppercase | ||
const toUpper = cstVisitor({ | ||
keyword: (kw) => { | ||
kw.text = kw.text.toUpperCase(); | ||
}, | ||
}); | ||
toUpper(cst); | ||
// Serialize back to SQL | ||
show(cst); // --> SELECT * FROM your_table | ||
show(cst); // --> SELECT * FROM my_table | ||
``` | ||
@@ -50,3 +60,3 @@ | ||
{ | ||
"type": "select_statement", | ||
"type": "select_stmt", | ||
"columns": [ | ||
@@ -81,3 +91,3 @@ { | ||
{ | ||
"type": "select_statement", | ||
"type": "select_stmt", | ||
"clauses": [ | ||
@@ -143,2 +153,38 @@ { | ||
## Development | ||
`yarn generate` will generate parser for each supported dialect. | ||
You can also target a specific dialect, like `yarn generate sqlite`. | ||
The testsuite contains two kinds of tests: | ||
- tests applicable for all dialects | ||
- tests applicable for only some specific dialects | ||
When running the testsuite one always needs to pick a dialect. | ||
For example `yarn test:sqlite` or `yarn test:mysql`. | ||
Running one of these commands will run the testsuite against the parser | ||
of that dialect. It will execute all the generic tests plus tests | ||
applicable for that dialect. | ||
`yarn test` will execute the testsuite for each supported dialect, | ||
covering all the possible combinations. | ||
### During development | ||
Start the parser-generator watch process in one terminal: | ||
``` | ||
yarn watch:generate | ||
``` | ||
and the tests watch process in another terminal: | ||
``` | ||
yarn test:sqlite --watch | ||
``` | ||
Note that `yarn test --watch` doesn't work. | ||
A separate watch process needs to be started manually for each dialect. | ||
## Acknowledgements | ||
@@ -145,0 +191,0 @@ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
2858984
35
105768
195
0