mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-18 00:56:02 +00:00
sql tree refactor
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import GridDisplay from "./GridDisplay";
|
||||
import { Select } from "@dbgate/sqltree";
|
||||
import { Select, treeToSql, dumpSqlSelect } from "@dbgate/sqltree";
|
||||
import { TableInfo, EngineDriver } from "@dbgate/types";
|
||||
import GridConfig from "./GridConfig";
|
||||
|
||||
@@ -14,9 +14,11 @@ export default class TableGridDisplay extends GridDisplay {
|
||||
}
|
||||
|
||||
createSelect() {
|
||||
const select = new Select();
|
||||
select.from = this.table;
|
||||
select.selectAll = true;
|
||||
const select: Select = {
|
||||
commandType: "select",
|
||||
from: this.table,
|
||||
selectAll: true
|
||||
};
|
||||
return select;
|
||||
}
|
||||
|
||||
@@ -25,7 +27,7 @@ export default class TableGridDisplay extends GridDisplay {
|
||||
if (this.driver.dialect.limitSelect) select.topRecords = count;
|
||||
if (this.driver.dialect.rangeSelect)
|
||||
select.range = { offset: offset, limit: count };
|
||||
const sql = select.toSql(this.driver);
|
||||
const sql = treeToSql(this.driver, select, dumpSqlSelect);
|
||||
return sql;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {}
|
||||
// }
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { SqlDumper } from "@dbgate/types";
|
||||
// import { SqlDumper } from "@dbgate/types";
|
||||
|
||||
export abstract class Condition {
|
||||
abstract dumpSql(dumper: SqlDumper) ;
|
||||
}
|
||||
// export abstract class Condition {
|
||||
// abstract dumpSql(dumper: SqlDumper) ;
|
||||
// }
|
||||
|
||||
export abstract class UnaryCondition extends Condition {
|
||||
// expr: Expresssion;
|
||||
}
|
||||
// export abstract class UnaryCondition extends Condition {
|
||||
// // expr: Expresssion;
|
||||
// }
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
export abstract class Expression {
|
||||
// export abstract class Expression {
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
import { Command } from "./Command";
|
||||
import { NamedObjectInfo, RangeDefinition, SqlDumper } from "@dbgate/types";
|
||||
// import { Command } from "./Command";
|
||||
// import { NamedObjectInfo, RangeDefinition, SqlDumper } from "@dbgate/types";
|
||||
|
||||
export class Select extends Command {
|
||||
topRecords: number;
|
||||
from: NamedObjectInfo;
|
||||
range: RangeDefinition;
|
||||
distinct = false;
|
||||
selectAll = false;
|
||||
// export class Select extends Command {
|
||||
// topRecords: number;
|
||||
// from: NamedObjectInfo;
|
||||
// range: RangeDefinition;
|
||||
// distinct = false;
|
||||
// selectAll = false;
|
||||
|
||||
dumpSql(dumper: SqlDumper) {
|
||||
dumper.put("^select ");
|
||||
if (this.topRecords) {
|
||||
dumper.put("^top %s ", this.topRecords);
|
||||
}
|
||||
if (this.distinct) {
|
||||
dumper.put("^distinct ");
|
||||
}
|
||||
if (this.selectAll) {
|
||||
dumper.put("* ");
|
||||
} else {
|
||||
// TODO
|
||||
}
|
||||
dumper.put("^from %f ", this.from);
|
||||
if (this.range) {
|
||||
dumper.put("^limit %s ^offset %s ", this.range.limit, this.range.offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
// dumpSql(dumper: SqlDumper) {
|
||||
// dumper.put("^select ");
|
||||
// if (this.topRecords) {
|
||||
// dumper.put("^top %s ", this.topRecords);
|
||||
// }
|
||||
// if (this.distinct) {
|
||||
// dumper.put("^distinct ");
|
||||
// }
|
||||
// if (this.selectAll) {
|
||||
// dumper.put("* ");
|
||||
// } else {
|
||||
// // TODO
|
||||
// }
|
||||
// dumper.put("^from %f ", this.from);
|
||||
// if (this.range) {
|
||||
// dumper.put("^limit %s ^offset %s ", this.range.limit, this.range.offset);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -1,78 +1,78 @@
|
||||
import { SqlDumper, NamedObjectInfo } from "@dbgate/types";
|
||||
import { Select } from "./Select";
|
||||
// import { SqlDumper, NamedObjectInfo } from "@dbgate/types";
|
||||
// import { Select } from "./Select";
|
||||
|
||||
export class Source {
|
||||
name: NamedObjectInfo;
|
||||
alias: string;
|
||||
subQuery: Select;
|
||||
subQueryString: string;
|
||||
// export class Source {
|
||||
// name: NamedObjectInfo;
|
||||
// alias: string;
|
||||
// subQuery: Select;
|
||||
// subQueryString: string;
|
||||
|
||||
dumpSqlDef(dumper: SqlDumper) {
|
||||
let sources = 0;
|
||||
if (this.name != null) sources++;
|
||||
if (this.subQuery != null) sources++;
|
||||
if (this.subQueryString != null) sources++;
|
||||
if (sources != 1)
|
||||
throw new Error("sqltree.Source should have exactly one source");
|
||||
// dumpSqlDef(dumper: SqlDumper) {
|
||||
// let sources = 0;
|
||||
// if (this.name != null) sources++;
|
||||
// if (this.subQuery != null) sources++;
|
||||
// if (this.subQueryString != null) sources++;
|
||||
// if (sources != 1)
|
||||
// throw new Error("sqltree.Source should have exactly one source");
|
||||
|
||||
if (this.name != null) {
|
||||
dumper.put("%f", this.name);
|
||||
}
|
||||
if (this.subQuery) {
|
||||
dumper.put("(");
|
||||
this.subQuery.dumpSql(dumper);
|
||||
dumper.put(")");
|
||||
}
|
||||
if (this.subQueryString) {
|
||||
dumper.put("(");
|
||||
dumper.putRaw(this.subQueryString);
|
||||
dumper.put(")");
|
||||
}
|
||||
if (this.alias) {
|
||||
dumper.put(" %i", this.alias);
|
||||
}
|
||||
}
|
||||
// if (this.name != null) {
|
||||
// dumper.put("%f", this.name);
|
||||
// }
|
||||
// if (this.subQuery) {
|
||||
// dumper.put("(");
|
||||
// this.subQuery.dumpSql(dumper);
|
||||
// dumper.put(")");
|
||||
// }
|
||||
// if (this.subQueryString) {
|
||||
// dumper.put("(");
|
||||
// dumper.putRaw(this.subQueryString);
|
||||
// dumper.put(")");
|
||||
// }
|
||||
// if (this.alias) {
|
||||
// dumper.put(" %i", this.alias);
|
||||
// }
|
||||
// }
|
||||
|
||||
dumpSqlRef(dumper: SqlDumper) {
|
||||
if (this.alias != null) {
|
||||
dumper.put("%i", this.alias);
|
||||
return true;
|
||||
} else if (this.name != null) {
|
||||
dumper.put("%f", this.name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// dumpSqlRef(dumper: SqlDumper) {
|
||||
// if (this.alias != null) {
|
||||
// dumper.put("%i", this.alias);
|
||||
// return true;
|
||||
// } else if (this.name != null) {
|
||||
// dumper.put("%f", this.name);
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
class Relation {
|
||||
source:Source;
|
||||
joinType: string;
|
||||
// conditions:
|
||||
// class Relation {
|
||||
// source:Source;
|
||||
// joinType: string;
|
||||
// // conditions:
|
||||
|
||||
|
||||
// dumpSqlRef(dumper: SqlDumper) {
|
||||
// // dumpSqlRef(dumper: SqlDumper) {
|
||||
|
||||
// dumper.put("&n");
|
||||
// dumper.putRaw(this.joinType);
|
||||
// dumper.put(" ");
|
||||
// this.source.dumpSqlDef(dumper)
|
||||
// if (Conditions.Any())
|
||||
// {
|
||||
// dumper.put(" ^on ");
|
||||
// bool was = false;
|
||||
// foreach (var cond in Conditions)
|
||||
// {
|
||||
// if (was) dumper.put(" ^and ");
|
||||
// cond.GenSql(dmp);
|
||||
// was = true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// // dumper.put("&n");
|
||||
// // dumper.putRaw(this.joinType);
|
||||
// // dumper.put(" ");
|
||||
// // this.source.dumpSqlDef(dumper)
|
||||
// // if (Conditions.Any())
|
||||
// // {
|
||||
// // dumper.put(" ^on ");
|
||||
// // bool was = false;
|
||||
// // foreach (var cond in Conditions)
|
||||
// // {
|
||||
// // if (was) dumper.put(" ^and ");
|
||||
// // cond.GenSql(dmp);
|
||||
// // was = true;
|
||||
// // }
|
||||
// // }
|
||||
// // }
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
export class FromDefinition {
|
||||
source: Source;
|
||||
relations: Relation[] = [];
|
||||
}
|
||||
// export class FromDefinition {
|
||||
// source: Source;
|
||||
// relations: Relation[] = [];
|
||||
// }
|
||||
|
||||
29
packages/sqltree/src/dumpSqlCommand.ts
Normal file
29
packages/sqltree/src/dumpSqlCommand.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
20
packages/sqltree/src/dumpSqlExpression.ts
Normal file
20
packages/sqltree/src/dumpSqlExpression.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
40
packages/sqltree/src/dumpSqlSource.ts
Normal file
40
packages/sqltree/src/dumpSqlSource.ts
Normal 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;
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
export { Select } from "./Select";
|
||||
export { Command } from "./Command";
|
||||
export * from "./types";
|
||||
export * from "./dumpSqlCommand";
|
||||
export * from "./treeToSql";
|
||||
|
||||
11
packages/sqltree/src/treeToSql.ts
Normal file
11
packages/sqltree/src/treeToSql.ts
Normal 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;
|
||||
}
|
||||
62
packages/sqltree/src/types.ts
Normal file
62
packages/sqltree/src/types.ts
Normal 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;
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ export default function TableCreateScriptTab({ conid, database, schemaName, pure
|
||||
// console.log(tableInfo);
|
||||
|
||||
const driver = engines(connnection.engine);
|
||||
const dumper = driver.createDumper();
|
||||
if (tableInfo) dumper.createTable(tableInfo);
|
||||
const dmp = driver.createDumper();
|
||||
if (tableInfo) dmp.createTable(tableInfo);
|
||||
|
||||
return <SqlEditor engine={connnection && connnection.engine} value={dumper.s} />;
|
||||
return <SqlEditor engine={connnection && connnection.engine} value={dmp.s} />;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user