sql tree refactor

This commit is contained in:
Jan Prochazka
2020-03-05 12:23:07 +01:00
parent bf607fcb06
commit 95ae39e0de
13 changed files with 291 additions and 123 deletions

View File

@@ -1,5 +1,5 @@
import GridDisplay from "./GridDisplay"; import GridDisplay from "./GridDisplay";
import { Select } from "@dbgate/sqltree"; import { Select, treeToSql, dumpSqlSelect } from "@dbgate/sqltree";
import { TableInfo, EngineDriver } from "@dbgate/types"; import { TableInfo, EngineDriver } from "@dbgate/types";
import GridConfig from "./GridConfig"; import GridConfig from "./GridConfig";
@@ -14,9 +14,11 @@ export default class TableGridDisplay extends GridDisplay {
} }
createSelect() { createSelect() {
const select = new Select(); const select: Select = {
select.from = this.table; commandType: "select",
select.selectAll = true; from: this.table,
selectAll: true
};
return select; return select;
} }
@@ -25,7 +27,7 @@ export default class TableGridDisplay extends GridDisplay {
if (this.driver.dialect.limitSelect) select.topRecords = count; if (this.driver.dialect.limitSelect) select.topRecords = count;
if (this.driver.dialect.rangeSelect) if (this.driver.dialect.rangeSelect)
select.range = { offset: offset, limit: count }; select.range = { offset: offset, limit: count };
const sql = select.toSql(this.driver); const sql = treeToSql(this.driver, select, dumpSqlSelect);
return sql; return sql;
} }
} }

View File

@@ -1,11 +1,14 @@
import { EngineDriver, SqlDumper } from "@dbgate/types"; import { NamedObjectInfo, RangeDefinition } from "@dbgate/types";
export class Command {
toSql(driver: EngineDriver) {
const dumper = driver.createDumper();
this.dumpSql(dumper);
return dumper.s;
}
dumpSql(dumper: SqlDumper) {} // import { EngineDriver, SqlDumper } from "@dbgate/types";
}
// export class Command {
// toSql(driver: EngineDriver) {
// const dumper = driver.createDumper();
// this.dumpSql(dumper);
// return dumper.s;
// }
// dumpSql(dumper: SqlDumper) {}
// }

View File

@@ -1,9 +1,9 @@
import { SqlDumper } from "@dbgate/types"; // import { SqlDumper } from "@dbgate/types";
export abstract class Condition { // export abstract class Condition {
abstract dumpSql(dumper: SqlDumper) ; // abstract dumpSql(dumper: SqlDumper) ;
} // }
export abstract class UnaryCondition extends Condition { // export abstract class UnaryCondition extends Condition {
// expr: Expresssion; // // expr: Expresssion;
} // }

View File

@@ -1,4 +1,4 @@
export abstract class Expression { // export abstract class Expression {
} // }

View File

@@ -1,29 +1,29 @@
import { Command } from "./Command"; // import { Command } from "./Command";
import { NamedObjectInfo, RangeDefinition, SqlDumper } from "@dbgate/types"; // import { NamedObjectInfo, RangeDefinition, SqlDumper } from "@dbgate/types";
export class Select extends Command { // export class Select extends Command {
topRecords: number; // topRecords: number;
from: NamedObjectInfo; // from: NamedObjectInfo;
range: RangeDefinition; // range: RangeDefinition;
distinct = false; // distinct = false;
selectAll = false; // selectAll = false;
dumpSql(dumper: SqlDumper) { // dumpSql(dumper: SqlDumper) {
dumper.put("^select "); // dumper.put("^select ");
if (this.topRecords) { // if (this.topRecords) {
dumper.put("^top %s ", this.topRecords); // dumper.put("^top %s ", this.topRecords);
} // }
if (this.distinct) { // if (this.distinct) {
dumper.put("^distinct "); // dumper.put("^distinct ");
} // }
if (this.selectAll) { // if (this.selectAll) {
dumper.put("* "); // dumper.put("* ");
} else { // } else {
// TODO // // TODO
} // }
dumper.put("^from %f ", this.from); // dumper.put("^from %f ", this.from);
if (this.range) { // if (this.range) {
dumper.put("^limit %s ^offset %s ", this.range.limit, this.range.offset); // dumper.put("^limit %s ^offset %s ", this.range.limit, this.range.offset);
} // }
} // }
} // }

View File

@@ -1,78 +1,78 @@
import { SqlDumper, NamedObjectInfo } from "@dbgate/types"; // import { SqlDumper, NamedObjectInfo } from "@dbgate/types";
import { Select } from "./Select"; // import { Select } from "./Select";
export class Source { // export class Source {
name: NamedObjectInfo; // name: NamedObjectInfo;
alias: string; // alias: string;
subQuery: Select; // subQuery: Select;
subQueryString: string; // subQueryString: string;
dumpSqlDef(dumper: SqlDumper) { // dumpSqlDef(dumper: SqlDumper) {
let sources = 0; // let sources = 0;
if (this.name != null) sources++; // if (this.name != null) sources++;
if (this.subQuery != null) sources++; // if (this.subQuery != null) sources++;
if (this.subQueryString != null) sources++; // if (this.subQueryString != null) sources++;
if (sources != 1) // if (sources != 1)
throw new Error("sqltree.Source should have exactly one source"); // throw new Error("sqltree.Source should have exactly one source");
if (this.name != null) { // if (this.name != null) {
dumper.put("%f", this.name); // dumper.put("%f", this.name);
} // }
if (this.subQuery) { // if (this.subQuery) {
dumper.put("("); // dumper.put("(");
this.subQuery.dumpSql(dumper); // this.subQuery.dumpSql(dumper);
dumper.put(")"); // dumper.put(")");
} // }
if (this.subQueryString) { // if (this.subQueryString) {
dumper.put("("); // dumper.put("(");
dumper.putRaw(this.subQueryString); // dumper.putRaw(this.subQueryString);
dumper.put(")"); // dumper.put(")");
} // }
if (this.alias) { // if (this.alias) {
dumper.put(" %i", this.alias); // dumper.put(" %i", this.alias);
} // }
} // }
dumpSqlRef(dumper: SqlDumper) { // dumpSqlRef(dumper: SqlDumper) {
if (this.alias != null) { // if (this.alias != null) {
dumper.put("%i", this.alias); // dumper.put("%i", this.alias);
return true; // return true;
} else if (this.name != null) { // } else if (this.name != null) {
dumper.put("%f", this.name); // dumper.put("%f", this.name);
return true; // return true;
} // }
return false; // return false;
} // }
} // }
class Relation { // class Relation {
source:Source; // source:Source;
joinType: string; // joinType: string;
// conditions: // // conditions:
// dumpSqlRef(dumper: SqlDumper) { // // dumpSqlRef(dumper: SqlDumper) {
// dumper.put("&n"); // // dumper.put("&n");
// dumper.putRaw(this.joinType); // // dumper.putRaw(this.joinType);
// dumper.put(" "); // // dumper.put(" ");
// this.source.dumpSqlDef(dumper) // // this.source.dumpSqlDef(dumper)
// if (Conditions.Any()) // // if (Conditions.Any())
// { // // {
// dumper.put(" ^on "); // // dumper.put(" ^on ");
// bool was = false; // // bool was = false;
// foreach (var cond in Conditions) // // foreach (var cond in Conditions)
// { // // {
// if (was) dumper.put(" ^and "); // // if (was) dumper.put(" ^and ");
// cond.GenSql(dmp); // // cond.GenSql(dmp);
// was = true; // // was = true;
// } // // }
// } // // }
// } // // }
} // }
export class FromDefinition { // export class FromDefinition {
source: Source; // source: Source;
relations: Relation[] = []; // relations: Relation[] = [];
} // }

View File

@@ -0,0 +1,29 @@
import { SqlDumper } from "@dbgate/types";
import { Command, Select } from "./types";
export function dumpSqlSelect(dmp: SqlDumper, select: Select) {
dmp.put("^select ");
if (select.topRecords) {
dmp.put("^top %s ", select.topRecords);
}
if (select.distinct) {
dmp.put("^distinct ");
}
if (select.selectAll) {
dmp.put("* ");
} else {
// TODO
}
dmp.put("^from %f ", select.from);
if (select.range) {
dmp.put("^limit %s ^offset %s ", select.range.limit, select.range.offset);
}
}
export function dumpSqlCommand(dmp: SqlDumper, command: Command) {
switch (command.commandType) {
case "select":
dumpSqlSelect(dmp, command as Select);
break;
}
}

View File

@@ -0,0 +1,20 @@
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) {
switch (expr.exprType) {
case "column":
dumpSqlColumnRef(dumper, expr as ColumnRefExpression);
break;
}
}

View File

@@ -0,0 +1,40 @@
import { Source } from "./types";
import { SqlDumper } from "@dbgate/types";
import { dumpSqlSelect } from "./dumpSqlCommand";
export function dumpSqlSourceDef(dmp: SqlDumper, source: Source) {
let sources = 0;
if (source.name != null) sources++;
if (source.subQuery != null) sources++;
if (source.subQueryString != null) sources++;
if (sources != 1)
throw new Error("sqltree.Source should have exactly one source");
if (source.name != null) {
dmp.put("%f", source.name);
}
if (source.subQuery) {
dmp.put("(");
dumpSqlSelect(dmp, source.subQuery);
dmp.put(")");
}
if (source.subQueryString) {
dmp.put("(");
dmp.putRaw(source.subQueryString);
dmp.put(")");
}
if (source.alias) {
dmp.put(" %i", this.alias);
}
}
export function dumpSqlSourceRef(dmp: SqlDumper, source: Source) {
if (source.alias) {
dmp.put("%i", source.alias);
return true;
} else if (source.name) {
dmp.put("%f", source.name);
return true;
}
return false;
}

View File

@@ -1,2 +1,3 @@
export { Select } from "./Select"; export * from "./types";
export { Command } from "./Command"; export * from "./dumpSqlCommand";
export * from "./treeToSql";

View File

@@ -0,0 +1,11 @@
import { EngineDriver, SqlDumper } from "@dbgate/types";
export function treeToSql<T>(
driver: EngineDriver,
object: T,
func: (dmp: SqlDumper, obj: T) => void
) {
const dmp = driver.createDumper();
func(dmp, object);
return dmp.s;
}

View File

@@ -0,0 +1,62 @@
import { NamedObjectInfo, RangeDefinition } from "@dbgate/types";
export interface Command {
commandType: "select";
}
export interface Select extends Command {
from: NamedObjectInfo;
topRecords?: number;
range?: RangeDefinition;
distinct?: boolean;
selectAll?: boolean;
}
export interface Condition {
conditionType: "eq" | "not";
}
export interface UnaryCondition extends Condition {
expr: Expression;
}
export interface BinaryCondition extends Condition {
left: Expression;
right: Expression;
}
export interface NotCondition extends UnaryCondition {
conditionType: "not";
}
export interface Source {
name: NamedObjectInfo;
alias: string;
subQuery: Select;
subQueryString: string;
}
export type JoinType = "LEFT JOIN" | "INNER JOIN" | "RIGHT JOIN";
export interface Relation {
source: Source;
conditions: Condition[];
joinType: JoinType;
}
export interface Expression {
exprType: "column" | "value" | "string" | "literal" | "count";
}
export interface ColumnRefExpression extends Expression {
exprType: "column";
columnName: string;
source: Source;
}
export interface ValueExpression extends Expression {
exprType: "value";
value: any;
}

View File

@@ -11,8 +11,8 @@ export default function TableCreateScriptTab({ conid, database, schemaName, pure
// console.log(tableInfo); // console.log(tableInfo);
const driver = engines(connnection.engine); const driver = engines(connnection.engine);
const dumper = driver.createDumper(); const dmp = driver.createDumper();
if (tableInfo) dumper.createTable(tableInfo); if (tableInfo) dmp.createTable(tableInfo);
return <SqlEditor engine={connnection && connnection.engine} value={dumper.s} />; return <SqlEditor engine={connnection && connnection.engine} value={dmp.s} />;
} }