mirror of
https://github.com/dbgate/dbgate
synced 2024-11-07 20:26:23 +00:00
parent filter implementation
This commit is contained in:
parent
1731b7e4a3
commit
339588b8a0
@ -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(
|
||||||
|
@ -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
|
||||||
)}
|
)}
|
||||||
|
Loading…
Reference in New Issue
Block a user