parent filter implementation

This commit is contained in:
Jan Prochazka 2022-08-07 19:16:23 +02:00
parent 1731b7e4a3
commit 339588b8a0
2 changed files with 173 additions and 16 deletions

View File

@ -1,4 +1,12 @@
import { ColumnInfo, DatabaseInfo, ForeignKeyInfo, RangeDefinition, TableInfo, ViewInfo } from 'dbgate-types'; import {
ColumnInfo,
DatabaseInfo,
ForeignKeyInfo,
NamedObjectInfo,
RangeDefinition,
TableInfo,
ViewInfo,
} from 'dbgate-types';
import { import {
ChangePerspectiveConfigFunc, ChangePerspectiveConfigFunc,
MultipleDatabaseInfo, MultipleDatabaseInfo,
@ -23,7 +31,7 @@ import {
import stableStringify from 'json-stable-stringify'; import stableStringify from 'json-stable-stringify';
import { getFilterType, parseFilter } from 'dbgate-filterparser'; import { getFilterType, parseFilter } from 'dbgate-filterparser';
import { FilterType } from 'dbgate-filterparser/lib/types'; import { FilterType } from 'dbgate-filterparser/lib/types';
import { Condition, Expression } from 'dbgate-sqltree'; import { Condition, Expression, Select } from 'dbgate-sqltree';
import { getPerspectiveDefaultColumns } from './getPerspectiveDefaultColumns'; import { getPerspectiveDefaultColumns } from './getPerspectiveDefaultColumns';
export interface PerspectiveDataLoadPropsWithNode { export interface PerspectiveDataLoadPropsWithNode {
@ -79,10 +87,17 @@ export abstract class PerspectiveTreeNode {
get tableCode() { get tableCode() {
return null; return null;
} }
get namedObject(): NamedObjectInfo {
return null;
}
abstract getNodeLoadProps(parentRows: any[]): PerspectiveDataLoadProps; abstract getNodeLoadProps(parentRows: any[]): PerspectiveDataLoadProps;
get isRoot() { get isRoot() {
return this.parentNode == null; return this.parentNode == null;
} }
get rootNode(): PerspectiveTreeNode {
if (this.isRoot) return this;
return this.parentNode?.rootNode;
}
matchChildRow(parentRow: any, childRow: any): boolean { matchChildRow(parentRow: any, childRow: any): boolean {
return true; return true;
} }
@ -131,7 +146,7 @@ export abstract class PerspectiveTreeNode {
return []; return [];
} }
parseFilterCondition() { parseFilterCondition(source = null) {
return null; return null;
} }
@ -182,8 +197,11 @@ export abstract class PerspectiveTreeNode {
); );
} }
getChildrenCondition(): Condition { getChildrenCondition(source = null): Condition {
const conditions = _compact(this.childNodes.map(x => x.parseFilterCondition())); const conditions = _compact([
...this.childNodes.map(x => x.parseFilterCondition(source)),
...this.buildParentFilterConditions(),
]);
if (conditions.length == 0) { if (conditions.length == 0) {
return null; return null;
} }
@ -259,6 +277,60 @@ export abstract class PerspectiveTreeNode {
get isParentFilter() { get isParentFilter() {
return !!(this.config.parentFilters || []).find(x => x.uniqueName == this.uniqueName); return !!(this.config.parentFilters || []).find(x => x.uniqueName == this.uniqueName);
} }
buildParentFilterConditions(): Condition[] {
const leafNodes = _compact(
(this.config?.parentFilters || []).map(x => this.rootNode.findNodeByUniqueName(x.uniqueName))
);
const conditions: Condition[] = _compact(
leafNodes.map(leafNode => {
if (leafNode == this) return null;
const select: Select = {
commandType: 'select',
from: {
name: leafNode.namedObject,
alias: 'pert_0',
relations: [],
},
selectAll: true,
};
let lastNode = leafNode;
let node = leafNode;
let index = 1;
let lastAlias = 'pert_0';
while (node?.parentNode && node?.parentNode != this) {
node = node.parentNode;
let alias = `pert_${index}`;
select.from.relations.push({
joinType: 'INNER JOIN',
alias,
name: node.namedObject,
conditions: lastNode.getParentJoinCondition(lastAlias, alias),
});
lastAlias = alias;
lastNode = node;
}
if (node?.parentNode != this) return null;
select.where = {
conditionType: 'and',
conditions: _compact([
...lastNode.getParentJoinCondition(lastAlias, this.namedObject.pureName),
leafNode.getChildrenCondition({ alias: 'pert_0' }),
]),
};
return {
conditionType: 'exists',
subQuery: select,
};
})
);
return conditions;
}
getParentJoinCondition(alias: string, parentAlias: string): Condition[] {
return [];
}
} }
export class PerspectiveTableColumnNode extends PerspectiveTreeNode { export class PerspectiveTableColumnNode extends PerspectiveTreeNode {
@ -305,6 +377,27 @@ export class PerspectiveTableColumnNode extends PerspectiveTreeNode {
return [this.foreignKey.columns[0].refColumnName]; return [this.foreignKey.columns[0].refColumnName];
} }
getParentJoinCondition(alias: string, parentAlias: string): Condition[] {
if (!this.foreignKey) return [];
return this.foreignKey.columns.map(column => {
const res: Condition = {
conditionType: 'binary',
operator: '=',
left: {
exprType: 'column',
columnName: column.columnName,
source: { alias: parentAlias },
},
right: {
exprType: 'column',
columnName: column.refColumnName,
source: { alias },
},
};
return res;
});
}
getNodeLoadProps(parentRows: any[]): PerspectiveDataLoadProps { getNodeLoadProps(parentRows: any[]): PerspectiveDataLoadProps {
if (!this.foreignKey) return null; if (!this.foreignKey) return null;
return { return {
@ -388,7 +481,7 @@ export class PerspectiveTableColumnNode extends PerspectiveTreeNode {
}; };
} }
parseFilterCondition() { parseFilterCondition(source = null): Condition {
const filter = this.getFilter(); const filter = this.getFilter();
if (!filter) return null; if (!filter) return null;
const condition = parseFilter(filter, this.filterType); const condition = parseFilter(filter, this.filterType);
@ -398,11 +491,10 @@ export class PerspectiveTableColumnNode extends PerspectiveTreeNode {
return { return {
exprType: 'column', exprType: 'column',
columnName: this.column.columnName, columnName: this.column.columnName,
source,
}; };
} }
}); });
return condition;
} }
get headerTableAttributes() { get headerTableAttributes() {
@ -423,6 +515,16 @@ export class PerspectiveTableColumnNode extends PerspectiveTreeNode {
} }
return `${this.table.schemaName}|${this.table.pureName}`; return `${this.table.schemaName}|${this.table.pureName}`;
} }
get namedObject(): NamedObjectInfo {
if (this.foreignKey) {
return {
schemaName: this.foreignKey.refSchemaName,
pureName: this.foreignKey.refTableName,
};
}
return null;
}
} }
export class PerspectiveTableNode extends PerspectiveTreeNode { export class PerspectiveTableNode extends PerspectiveTreeNode {
@ -493,6 +595,13 @@ export class PerspectiveTableNode extends PerspectiveTreeNode {
get tableCode() { get tableCode() {
return `${this.table.schemaName}|${this.table.pureName}`; return `${this.table.schemaName}|${this.table.pureName}`;
} }
get namedObject(): NamedObjectInfo {
return {
schemaName: this.table.schemaName,
pureName: this.table.pureName,
};
}
} }
// export class PerspectiveViewNode extends PerspectiveTreeNode { // export class PerspectiveViewNode extends PerspectiveTreeNode {
@ -616,6 +725,27 @@ export class PerspectiveTableReferenceNode extends PerspectiveTableNode {
} }
return super.codeName; return super.codeName;
} }
getParentJoinCondition(alias: string, parentAlias: string): Condition[] {
if (!this.foreignKey) return [];
return this.foreignKey.columns.map(column => {
const res: Condition = {
conditionType: 'binary',
operator: '=',
left: {
exprType: 'column',
columnName: column.refColumnName,
source: { alias: parentAlias },
},
right: {
exprType: 'column',
columnName: column.columnName,
source: { alias },
},
};
return res;
});
}
} }
export class PerspectiveCustomJoinTreeNode extends PerspectiveTableNode { export class PerspectiveCustomJoinTreeNode extends PerspectiveTableNode {
@ -682,6 +812,26 @@ export class PerspectiveCustomJoinTreeNode extends PerspectiveTableNode {
get customJoinConfig(): PerspectiveCustomJoinConfig { get customJoinConfig(): PerspectiveCustomJoinConfig {
return this.customJoin; return this.customJoin;
} }
getParentJoinCondition(alias: string, parentAlias: string): Condition[] {
return this.customJoin.columns.map(column => {
const res: Condition = {
conditionType: 'binary',
operator: '=',
left: {
exprType: 'column',
columnName: column.baseColumnName,
source: { alias: parentAlias },
},
right: {
exprType: 'column',
columnName: column.refColumnName,
source: { alias },
},
};
return res;
});
}
} }
export function getTableChildPerspectiveNodes( export function getTableChildPerspectiveNodes(

View File

@ -219,20 +219,26 @@
res.push({ res.push({
text: 'Cancel filter parent rows', text: 'Cancel filter parent rows',
onClick: () => { onClick: () => {
setConfig(cfg => ({ setConfig(
...cfg, cfg => ({
parentFilters: cfg.parentFilters.filter(x => x.uniqueName != tableNode.uniqueName), ...cfg,
})); parentFilters: cfg.parentFilters.filter(x => x.uniqueName != tableNode.uniqueName),
}),
true
);
}, },
}); });
} else { } else {
res.push({ res.push({
text: 'Filter parent rows', text: 'Filter parent rows',
onClick: () => { onClick: () => {
setConfig(cfg => ({ setConfig(
...cfg, cfg => ({
parentFilters: [...(cfg.parentFilters || []), { uniqueName: tableNode.uniqueName }], ...cfg,
})); parentFilters: [...(cfg.parentFilters || []), { uniqueName: tableNode.uniqueName }],
}),
true
);
}, },
}); });
} }
@ -476,6 +482,7 @@
cfg => ({ cfg => ({
...cfg, ...cfg,
filters: {}, filters: {},
parentFilters: [],
}), }),
true true
)} )}