query designer - grop filter (having clause)

This commit is contained in:
Jan Prochazka
2020-12-30 15:55:53 +01:00
parent 5a42e8c9ae
commit 351ac5e6a7
5 changed files with 90 additions and 33 deletions

View File

@@ -36,6 +36,11 @@ export function dumpSqlSelect(dmp: SqlDumper, cmd: Select) {
dmp.putCollection(', ', cmd.groupBy, (expr) => dumpSqlExpression(dmp, expr)); dmp.putCollection(', ', cmd.groupBy, (expr) => dumpSqlExpression(dmp, expr));
dmp.put('&n'); dmp.put('&n');
} }
if (cmd.having) {
dmp.put('&n^having ');
dumpSqlCondition(dmp, cmd.having);
dmp.put('&n');
}
if (cmd.orderBy) { if (cmd.orderBy) {
dmp.put('&n^order ^by '); dmp.put('&n^order ^by ');
dmp.putCollection(', ', cmd.orderBy, (expr) => { dmp.putCollection(', ', cmd.orderBy, (expr) => {

View File

@@ -16,6 +16,7 @@ export interface Select {
orderBy?: OrderByExpression[]; orderBy?: OrderByExpression[];
groupBy?: Expression[]; groupBy?: Expression[];
where?: Condition; where?: Condition;
having?: Condition;
} }
export type UpdateField = Expression & { targetColumn: string }; export type UpdateField = Expression & { targetColumn: string };

View File

@@ -1,5 +1,14 @@
import _ from 'lodash'; import _ from 'lodash';
import { dumpSqlSelect, Select, JoinType, Condition, Relation, mergeConditions, Source } from 'dbgate-sqltree'; import {
dumpSqlSelect,
Select,
JoinType,
Condition,
Relation,
mergeConditions,
Source,
ResultField,
} 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';
import { DesignerComponent } from './DesignerComponentCreator'; import { DesignerComponent } from './DesignerComponentCreator';
@@ -93,34 +102,28 @@ export class DesignerQueryDumper {
} }
} }
run() { addGroupConditions(select: Select, tables: DesignerTableInfo[], selectIsGrouped: boolean) {
let res: Select = null; for (const column of this.designer.columns || []) {
for (const component of this.components) { if (!column.groupFilter) continue;
const select = this.dumpComponent(component); const table = (this.designer.tables || []).find((x) => x.designerId == column.designerId);
if (res == null) res = select; if (!table) continue;
else res = mergeSelectsFromDesigner(res, select); if (!tables.find((x) => x.designerId == table.designerId)) continue;
}
// top level cross join conditions const condition = parseFilter(column.groupFilter, findDesignerFilterType(column, this.designer));
const topLevelTables = this.topLevelTables; if (condition) {
for (const ref of this.designer.references || []) { select.having = mergeConditions(
if (referenceIsCrossJoin(ref) && referenceIsConnecting(ref, topLevelTables, topLevelTables)) { select.having,
res.where = mergeConditions(res.where, { _.cloneDeepWith(condition, (expr) => {
conditionType: 'and', if (expr.exprType == 'placeholder') {
conditions: getReferenceConditions(ref, this.designer), return this.getColumnOutputExpression(column, selectIsGrouped);
});
} }
} })
const topLevelColumns = (this.designer.columns || []).filter((col) =>
topLevelTables.find((tbl) => tbl.designerId == col.designerId)
); );
const selectIsGrouped = !!topLevelColumns.find((x) => x.isGrouped || (x.aggregate && x.aggregate != '---')); }
const outputColumns = topLevelColumns.filter((x) => x.isOutput); }
if (outputColumns.length == 0) { }
res.selectAll = true;
} else { getColumnOutputExpression(col, selectIsGrouped): ResultField {
res.columns = outputColumns.map((col) => {
const source = findQuerySource(this.designer, col.designerId); const source = findQuerySource(this.designer, col.designerId);
const { columnName } = col; const { columnName } = col;
let { alias } = col; let { alias } = col;
@@ -150,8 +153,37 @@ export class DesignerQueryDumper {
source, source,
}; };
} }
}
run() {
let res: Select = null;
for (const component of this.components) {
const select = this.dumpComponent(component);
if (res == null) res = select;
else res = mergeSelectsFromDesigner(res, select);
}
// top level cross join conditions
const topLevelTables = this.topLevelTables;
for (const ref of this.designer.references || []) {
if (referenceIsCrossJoin(ref) && referenceIsConnecting(ref, topLevelTables, topLevelTables)) {
res.where = mergeConditions(res.where, {
conditionType: 'and',
conditions: getReferenceConditions(ref, this.designer),
}); });
} }
}
const topLevelColumns = (this.designer.columns || []).filter((col) =>
topLevelTables.find((tbl) => tbl.designerId == col.designerId)
);
const selectIsGrouped = !!topLevelColumns.find((x) => x.isGrouped || (x.aggregate && x.aggregate != '---'));
const outputColumns = topLevelColumns.filter((x) => x.isOutput);
if (outputColumns.length == 0) {
res.selectAll = true;
} else {
res.columns = outputColumns.map((col) => this.getColumnOutputExpression(col, selectIsGrouped));
}
const groupedColumns = topLevelColumns.filter((x) => x.isGrouped); const groupedColumns = topLevelColumns.filter((x) => x.isGrouped);
if (groupedColumns.length > 0) { if (groupedColumns.length > 0) {
@@ -176,6 +208,7 @@ export class DesignerQueryDumper {
} }
this.addConditions(res, topLevelTables); this.addConditions(res, topLevelTables);
this.addGroupConditions(res, topLevelTables, selectIsGrouped);
return res; return res;
} }

View File

@@ -38,6 +38,8 @@ export default function QueryDesignColumns({ value, onChange }) {
[onChange] [onChange]
); );
const hasGroupedColumn = !!(columns || []).find((x) => x.isGrouped);
return ( return (
<TableControl rows={columns || []}> <TableControl rows={columns || []}>
<TableColumn fieldName="columnName" header="Column/Expression" /> <TableColumn fieldName="columnName" header="Column/Expression" />
@@ -136,6 +138,21 @@ export default function QueryDesignColumns({ value, onChange }) {
/> />
)} )}
/> />
{hasGroupedColumn && (
<TableColumn
fieldName="groupFilter"
header="Group filter"
formatter={(row) => (
<DataFilterControl
filterType={findDesignerFilterType(row, value)}
filter={row.groupFilter}
setFilter={(groupFilter) => {
changeColumn({ ...row, groupFilter });
}}
/>
)}
/>
)}
<TableColumn <TableColumn
fieldName="actions" fieldName="actions"
header="" header=""

View File

@@ -29,7 +29,8 @@ export type DesignerColumnInfo = {
aggregate?: string; aggregate?: string;
isOutput?: boolean; isOutput?: boolean;
sortOrder?: number; sortOrder?: number;
filter: string; filter?: string;
groupFilter?: string;
}; };
export type DesignerInfo = { export type DesignerInfo = {