From 9ef719ec95aa16ca8e84116065912b8f74a05e41 Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Thu, 5 Mar 2020 13:19:25 +0100 Subject: [PATCH] sqlgen --- packages/datalib/src/TableGridDisplay.ts | 11 ++++- packages/sqltree/src/createFunctions.ts | 10 +++++ packages/sqltree/src/dumpSqlCommand.ts | 18 ++++++-- packages/sqltree/src/dumpSqlCondition.ts | 15 +++++++ packages/sqltree/src/dumpSqlExpression.ts | 20 ++++----- packages/sqltree/src/dumpSqlSource.ts | 20 ++++++++- packages/sqltree/src/index.ts | 2 + packages/sqltree/src/types.ts | 55 +++++++++++++++-------- 8 files changed, 115 insertions(+), 36 deletions(-) create mode 100644 packages/sqltree/src/createFunctions.ts create mode 100644 packages/sqltree/src/dumpSqlCondition.ts diff --git a/packages/datalib/src/TableGridDisplay.ts b/packages/datalib/src/TableGridDisplay.ts index c2e99b00..aaeeaec1 100644 --- a/packages/datalib/src/TableGridDisplay.ts +++ b/packages/datalib/src/TableGridDisplay.ts @@ -16,8 +16,15 @@ export default class TableGridDisplay extends GridDisplay { createSelect() { const select: Select = { commandType: "select", - from: this.table, - selectAll: true + from: { + source: { name: this.table } + }, + columns: this.table.columns.map(col => ({ + expr: { + exprType: "column", + columnName: col.columnName + } + })) }; return select; } diff --git a/packages/sqltree/src/createFunctions.ts b/packages/sqltree/src/createFunctions.ts new file mode 100644 index 00000000..524ed134 --- /dev/null +++ b/packages/sqltree/src/createFunctions.ts @@ -0,0 +1,10 @@ +import { ResultField } from "./types"; + +export function createColumnResultField(columnName: string): ResultField { + return { + expr: { + exprType: "column", + columnName + } + }; +} diff --git a/packages/sqltree/src/dumpSqlCommand.ts b/packages/sqltree/src/dumpSqlCommand.ts index 0a2f232d..72a9d572 100644 --- a/packages/sqltree/src/dumpSqlCommand.ts +++ b/packages/sqltree/src/dumpSqlCommand.ts @@ -1,5 +1,7 @@ import { SqlDumper } from "@dbgate/types"; import { Command, Select } from "./types"; +import { dumpSqlExpression } from "./dumpSqlExpression"; +import { dumpSqlFromDefinition } from "./dumpSqlSource"; export function dumpSqlSelect(dmp: SqlDumper, select: Select) { dmp.put("^select "); @@ -11,10 +13,18 @@ export function dumpSqlSelect(dmp: SqlDumper, select: Select) { } if (select.selectAll) { dmp.put("* "); - } else { - // TODO } - dmp.put("^from %f ", select.from); + if (select.columns) { + if (select.selectAll) dmp.put("&n,"); + dmp.put("&>&n"); + dmp.putCollection(",&n", select.columns, fld => { + dumpSqlExpression(dmp, fld.expr); + if (fld.alias) dmp.put(" %i", fld.alias); + }); + dmp.put("&n&<"); + } + dmp.put("^from "); + dumpSqlFromDefinition(dmp, select.from); if (select.range) { dmp.put("^limit %s ^offset %s ", select.range.limit, select.range.offset); } @@ -23,7 +33,7 @@ export function dumpSqlSelect(dmp: SqlDumper, select: Select) { export function dumpSqlCommand(dmp: SqlDumper, command: Command) { switch (command.commandType) { case "select": - dumpSqlSelect(dmp, command as Select); + dumpSqlSelect(dmp, command); break; } } diff --git a/packages/sqltree/src/dumpSqlCondition.ts b/packages/sqltree/src/dumpSqlCondition.ts new file mode 100644 index 00000000..bccaa4b6 --- /dev/null +++ b/packages/sqltree/src/dumpSqlCondition.ts @@ -0,0 +1,15 @@ +import { SqlDumper } from "@dbgate/types"; +import { Condition, BinaryCondition } from "./types"; +import { dumpSqlExpression } from "./dumpSqlExpression"; + +export function dumpSqlCondition(dmp: SqlDumper, condition: Condition) { + switch (condition.conditionType) { + case "binary": + dmp.put("("); + dumpSqlExpression(dmp, condition.left); + dmp.put(" %s ", condition.operator); + dumpSqlExpression(dmp, condition.right); + dmp.put(")"); + break; + } +} diff --git a/packages/sqltree/src/dumpSqlExpression.ts b/packages/sqltree/src/dumpSqlExpression.ts index 00e7a358..a4cfe60e 100644 --- a/packages/sqltree/src/dumpSqlExpression.ts +++ b/packages/sqltree/src/dumpSqlExpression.ts @@ -2,19 +2,17 @@ import { SqlDumper } from "@dbgate/types"; import { Expression, ColumnRefExpression } from "./types"; import { dumpSqlSourceRef } from "./dumpSqlSource"; -function dumpSqlColumnRef(dumper: SqlDumper, expr: ColumnRefExpression) { - if (expr.source) { - if (dumpSqlSourceRef(dumper, expr.source)) { - dumper.put("."); - } - } - dumper.put("%i", expr.columnName); -} - -export function dumpSqlExpression(dumper: SqlDumper, expr: Expression) { +export function dumpSqlExpression(dmp: SqlDumper, expr: Expression) { switch (expr.exprType) { case "column": - dumpSqlColumnRef(dumper, expr as ColumnRefExpression); + { + if (expr.source) { + if (dumpSqlSourceRef(dmp, expr.source)) { + dmp.put("."); + } + } + dmp.put("%i", expr.columnName); + } break; } } diff --git a/packages/sqltree/src/dumpSqlSource.ts b/packages/sqltree/src/dumpSqlSource.ts index 7a133c76..1b17a352 100644 --- a/packages/sqltree/src/dumpSqlSource.ts +++ b/packages/sqltree/src/dumpSqlSource.ts @@ -1,6 +1,7 @@ -import { Source } from "./types"; +import { Source, FromDefinition, Relation } from "./types"; import { SqlDumper } from "@dbgate/types"; import { dumpSqlSelect } from "./dumpSqlCommand"; +import { dumpSqlCondition } from "./dumpSqlCondition"; export function dumpSqlSourceDef(dmp: SqlDumper, source: Source) { let sources = 0; @@ -38,3 +39,20 @@ export function dumpSqlSourceRef(dmp: SqlDumper, source: Source) { } return false; } + +export function dumpSqlRelation(dmp: SqlDumper, from: Relation) { + dmp.put("&n %k ", from.joinType); + dumpSqlSourceDef(dmp, from.source); + if (from.conditions) { + dmp.put(" ^on "); + dmp.putCollection(" ^and ", from.conditions, cond => + dumpSqlCondition(dmp, cond) + ); + } +} + +export function dumpSqlFromDefinition(dmp: SqlDumper, from: FromDefinition) { + dumpSqlSourceDef(dmp, from.source); + dmp.put(" "); + if (from.relations) from.relations.forEach(rel => dumpSqlRelation(dmp, rel)); +} diff --git a/packages/sqltree/src/index.ts b/packages/sqltree/src/index.ts index 9d0a99ad..cd60dbc0 100644 --- a/packages/sqltree/src/index.ts +++ b/packages/sqltree/src/index.ts @@ -1,3 +1,5 @@ export * from "./types"; export * from "./dumpSqlCommand"; export * from "./treeToSql"; +export * from "./dumpSqlSource"; +export * from "./dumpSqlCondition"; diff --git a/packages/sqltree/src/types.ts b/packages/sqltree/src/types.ts index 82451787..e0d89b59 100644 --- a/packages/sqltree/src/types.ts +++ b/packages/sqltree/src/types.ts @@ -1,27 +1,33 @@ import { NamedObjectInfo, RangeDefinition } from "@dbgate/types"; -export interface Command { +// export interface Command { +// } + +export interface Select { commandType: "select"; -} -export interface Select extends Command { - from: NamedObjectInfo; + from: FromDefinition; + columns?: ResultField[]; topRecords?: number; range?: RangeDefinition; distinct?: boolean; selectAll?: boolean; } -export interface Condition { - conditionType: "eq" | "not"; -} +export type Command = Select; -export interface UnaryCondition extends Condition { +// export interface Condition { +// conditionType: "eq" | "not" | "binary"; +// } + +export interface UnaryCondition { expr: Expression; } -export interface BinaryCondition extends Condition { +export interface BinaryCondition { + operator: "=" | "!=" | "<" | ">" | ">=" | "<="; + conditionType: "binary"; left: Expression; right: Expression; } @@ -30,11 +36,13 @@ export interface NotCondition extends UnaryCondition { conditionType: "not"; } +export type Condition = BinaryCondition | NotCondition; + export interface Source { - name: NamedObjectInfo; - alias: string; - subQuery: Select; - subQueryString: string; + name?: NamedObjectInfo; + alias?: string; + subQuery?: Select; + subQueryString?: string; } export type JoinType = "LEFT JOIN" | "INNER JOIN" | "RIGHT JOIN"; @@ -45,18 +53,29 @@ export interface Relation { joinType: JoinType; } -export interface Expression { - exprType: "column" | "value" | "string" | "literal" | "count"; +export interface FromDefinition { + source: Source; + relations?: Relation[]; } -export interface ColumnRefExpression extends Expression { +// export interface Expression { +// exprType: "column" | "value" | "string" | "literal" | "count"; +// } + +export interface ColumnRefExpression { exprType: "column"; columnName: string; - source: Source; + source?: Source; } -export interface ValueExpression extends Expression { +export interface ValueExpression { exprType: "value"; value: any; } +export type Expression = ColumnRefExpression | ValueExpression; + +export interface ResultField { + expr: ValueExpression | ColumnRefExpression; + alias?: string; +}