mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-22 22:46:01 +00:00
query designer SQL generator
This commit is contained in:
@@ -2,6 +2,7 @@ import { SqlDumper } from 'dbgate-types';
|
|||||||
import { Condition, BinaryCondition } from './types';
|
import { Condition, BinaryCondition } from './types';
|
||||||
import { dumpSqlExpression } from './dumpSqlExpression';
|
import { dumpSqlExpression } from './dumpSqlExpression';
|
||||||
import { link } from 'fs';
|
import { link } from 'fs';
|
||||||
|
import { dumpSqlSelect } from './dumpSqlCommand';
|
||||||
|
|
||||||
export function dumpSqlCondition(dmp: SqlDumper, condition: Condition) {
|
export function dumpSqlCondition(dmp: SqlDumper, condition: Condition) {
|
||||||
switch (condition.conditionType) {
|
switch (condition.conditionType) {
|
||||||
@@ -30,7 +31,7 @@ export function dumpSqlCondition(dmp: SqlDumper, condition: Condition) {
|
|||||||
break;
|
break;
|
||||||
case 'and':
|
case 'and':
|
||||||
case 'or':
|
case 'or':
|
||||||
dmp.putCollection(` ^${condition.conditionType} `, condition.conditions, cond => {
|
dmp.putCollection(` ^${condition.conditionType} `, condition.conditions, (cond) => {
|
||||||
dmp.putRaw('(');
|
dmp.putRaw('(');
|
||||||
dumpSqlCondition(dmp, cond);
|
dumpSqlCondition(dmp, cond);
|
||||||
dmp.putRaw(')');
|
dmp.putRaw(')');
|
||||||
@@ -51,5 +52,15 @@ export function dumpSqlCondition(dmp: SqlDumper, condition: Condition) {
|
|||||||
dumpSqlCondition(dmp, condition.condition);
|
dumpSqlCondition(dmp, condition.condition);
|
||||||
dmp.put(')');
|
dmp.put(')');
|
||||||
break;
|
break;
|
||||||
|
case 'exists':
|
||||||
|
dmp.put('^exists (');
|
||||||
|
dumpSqlSelect(dmp, condition.subQuery);
|
||||||
|
dmp.put(')');
|
||||||
|
break;
|
||||||
|
case 'notExists':
|
||||||
|
dmp.put('^not ^exists (');
|
||||||
|
dumpSqlSelect(dmp, condition.subQuery);
|
||||||
|
dmp.put(')');
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,23 @@ export interface CompoudCondition {
|
|||||||
conditions: Condition[];
|
conditions: Condition[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Condition = BinaryCondition | NotCondition | TestCondition | CompoudCondition | LikeCondition;
|
export interface ExistsCondition {
|
||||||
|
conditionType: 'exists';
|
||||||
|
subQuery: Select;
|
||||||
|
}
|
||||||
|
export interface NotExistsCondition {
|
||||||
|
conditionType: 'notExists';
|
||||||
|
subQuery: Select;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Condition =
|
||||||
|
| BinaryCondition
|
||||||
|
| NotCondition
|
||||||
|
| TestCondition
|
||||||
|
| CompoudCondition
|
||||||
|
| LikeCondition
|
||||||
|
| ExistsCondition
|
||||||
|
| NotExistsCondition;
|
||||||
|
|
||||||
export interface Source {
|
export interface Source {
|
||||||
name?: NamedObjectInfo;
|
name?: NamedObjectInfo;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { dumpSqlSelect, Select, JoinType, Condition } from 'dbgate-sqltree';
|
import { dumpSqlSelect, Select, JoinType, Condition, Relation } from 'dbgate-sqltree';
|
||||||
import { EngineDriver } from 'dbgate-types';
|
import { EngineDriver } from 'dbgate-types';
|
||||||
import { DesignerInfo, DesignerTableInfo, DesignerReferenceInfo, DesignerJoinType } from './types';
|
import { DesignerInfo, DesignerTableInfo, DesignerReferenceInfo, DesignerJoinType } from './types';
|
||||||
|
|
||||||
@@ -37,18 +37,51 @@ function findJoinType(
|
|||||||
table: DesignerTableInfo,
|
table: DesignerTableInfo,
|
||||||
dumpedTables: DesignerTableInfo[],
|
dumpedTables: DesignerTableInfo[],
|
||||||
references: DesignerReferenceInfo[],
|
references: DesignerReferenceInfo[],
|
||||||
joinTypes: DesignerJoinType[]
|
joinTypes = ['INNER JOIN', 'LEFT JOIN', 'RIGHT JOIN', 'FULL OUTER JOIN', 'WHERE EXISTS', 'WHERE NOT EXISTS']
|
||||||
): DesignerJoinType {
|
): DesignerJoinType {
|
||||||
const dumpedTableIds = dumpedTables.map((x) => x.designerId);
|
const dumpedTableIds = dumpedTables.map((x) => x.designerId);
|
||||||
const reference = references.find(
|
const reference = references.find(
|
||||||
(x) =>
|
(x) =>
|
||||||
(x.sourceId == table.designerId && dumpedTableIds.includes(x.targetId)) ||
|
joinTypes.includes(x.joinType) &&
|
||||||
(x.targetId == table.designerId && dumpedTableIds.includes(x.sourceId))
|
((x.sourceId == table.designerId && dumpedTableIds.includes(x.targetId)) ||
|
||||||
|
(x.targetId == table.designerId && dumpedTableIds.includes(x.sourceId)))
|
||||||
);
|
);
|
||||||
if (reference) return reference.joinType || 'CROSS JOIN';
|
if (reference) return reference.joinType || 'CROSS JOIN';
|
||||||
return 'CROSS JOIN';
|
return 'CROSS JOIN';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sortTablesByReferences(
|
||||||
|
dumpedTables: DesignerTableInfo[],
|
||||||
|
tables: DesignerTableInfo[],
|
||||||
|
references: DesignerReferenceInfo[],
|
||||||
|
joinTypes = ['INNER JOIN', 'LEFT JOIN', 'RIGHT JOIN', 'FULL OUTER JOIN', 'WHERE EXISTS', 'WHERE NOT EXISTS']
|
||||||
|
) {
|
||||||
|
const res = [];
|
||||||
|
const dumpedTableIds = dumpedTables.map((x) => x.designerId);
|
||||||
|
const toAdd = [...tables];
|
||||||
|
while (toAdd.length > 0) {
|
||||||
|
let found = false;
|
||||||
|
for (const test of toAdd) {
|
||||||
|
const reference = references.find(
|
||||||
|
(x) =>
|
||||||
|
joinTypes.includes(x.joinType) &&
|
||||||
|
((x.sourceId == test.designerId && dumpedTableIds.includes(x.targetId)) ||
|
||||||
|
(x.targetId == test.designerId && dumpedTableIds.includes(x.sourceId)))
|
||||||
|
);
|
||||||
|
if (reference) {
|
||||||
|
res.push(test);
|
||||||
|
_.remove(toAdd, (x) => x == test);
|
||||||
|
dumpedTableIds.push(test.designerId);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) break;
|
||||||
|
}
|
||||||
|
res.push(...toAdd);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
function findConditions(
|
function findConditions(
|
||||||
table: DesignerTableInfo,
|
table: DesignerTableInfo,
|
||||||
dumpedTables: DesignerTableInfo[],
|
dumpedTables: DesignerTableInfo[],
|
||||||
@@ -90,6 +123,24 @@ function findConditions(
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addRelations(
|
||||||
|
relations: Relation[],
|
||||||
|
tables: DesignerTableInfo[],
|
||||||
|
dumpedTables: DesignerTableInfo[],
|
||||||
|
designer: DesignerInfo
|
||||||
|
) {
|
||||||
|
for (const table of tables) {
|
||||||
|
if (dumpedTables.includes(table)) continue;
|
||||||
|
relations.push({
|
||||||
|
name: table,
|
||||||
|
alias: table.alias,
|
||||||
|
joinType: findJoinType(table, dumpedTables, designer.references) as JoinType,
|
||||||
|
conditions: findConditions(table, dumpedTables, designer.references, designer.tables),
|
||||||
|
});
|
||||||
|
dumpedTables.push(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default function generateDesignedQuery(designer: DesignerInfo, engine: EngineDriver) {
|
export default function generateDesignedQuery(designer: DesignerInfo, engine: EngineDriver) {
|
||||||
const { tables, columns, references } = designer;
|
const { tables, columns, references } = designer;
|
||||||
const primaryTable = findPrimaryTable(designer.tables);
|
const primaryTable = findPrimaryTable(designer.tables);
|
||||||
@@ -111,6 +162,7 @@ export default function generateDesignedQuery(designer: DesignerInfo, engine: En
|
|||||||
};
|
};
|
||||||
|
|
||||||
const dumpedTables = [primaryTable];
|
const dumpedTables = [primaryTable];
|
||||||
|
const conditions: Condition[] = [];
|
||||||
for (const component of components) {
|
for (const component of components) {
|
||||||
const subComponents = groupByComponents(
|
const subComponents = groupByComponents(
|
||||||
component,
|
component,
|
||||||
@@ -119,23 +171,46 @@ export default function generateDesignedQuery(designer: DesignerInfo, engine: En
|
|||||||
primaryTable
|
primaryTable
|
||||||
);
|
);
|
||||||
for (const subComponent of subComponents) {
|
for (const subComponent of subComponents) {
|
||||||
for (const table of subComponent) {
|
const sortedSubComponent = sortTablesByReferences(dumpedTables, subComponent, designer.references);
|
||||||
if (dumpedTables.includes(table)) continue;
|
const table0 = sortedSubComponent[0];
|
||||||
select.from.relations.push({
|
const joinType0 = findJoinType(table0, dumpedTables, designer.references);
|
||||||
name: table,
|
if (joinType0 == 'WHERE EXISTS' || joinType0 == 'WHERE NOT EXISTS') {
|
||||||
alias: table.alias,
|
const subselect: Select = {
|
||||||
joinType: findJoinType(table, dumpedTables, designer.references, [
|
commandType: 'select',
|
||||||
'INNER JOIN',
|
from: {
|
||||||
'LEFT JOIN',
|
name: table0,
|
||||||
'RIGHT JOIN',
|
alias: table0.alias,
|
||||||
'FULL OUTER JOIN',
|
relations: [],
|
||||||
]) as JoinType,
|
},
|
||||||
conditions: findConditions(table, dumpedTables, designer.references, designer.tables),
|
};
|
||||||
|
dumpedTables.push(table0);
|
||||||
|
addRelations(subselect.from.relations, sortedSubComponent, dumpedTables, designer);
|
||||||
|
conditions.push({
|
||||||
|
conditionType: joinType0 == 'WHERE EXISTS' ? 'exists' : 'notExists',
|
||||||
|
subQuery: subselect,
|
||||||
});
|
});
|
||||||
dumpedTables.push(table);
|
} else {
|
||||||
|
addRelations(select.from.relations, sortedSubComponent, dumpedTables, designer);
|
||||||
|
// for (const table of sortedSubComponent) {
|
||||||
|
|
||||||
|
// if (dumpedTables.includes(table)) continue;
|
||||||
|
// select.from.relations.push({
|
||||||
|
// name: table,
|
||||||
|
// alias: table.alias,
|
||||||
|
// joinType: findJoinType(table, dumpedTables, designer.references) as JoinType,
|
||||||
|
// conditions: findConditions(table, dumpedTables, designer.references, designer.tables),
|
||||||
|
// });
|
||||||
|
// dumpedTables.push(table);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (conditions.length > 0) {
|
||||||
|
select.where = {
|
||||||
|
conditionType: 'and',
|
||||||
|
conditions,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const dmp = engine.createDumper();
|
const dmp = engine.createDumper();
|
||||||
dumpSqlSelect(dmp, select);
|
dumpSqlSelect(dmp, select);
|
||||||
|
|||||||
Reference in New Issue
Block a user