From c3609e8c7b1af0525a68966188e1be60c5c5df04 Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Mon, 19 Aug 2024 12:49:26 +0200 Subject: [PATCH] filter behaviour WIP --- packages/datalib/src/CollectionGridDisplay.ts | 7 ++--- packages/datalib/src/GridDisplay.ts | 27 ++++++++++++------- packages/datalib/src/JslGridDisplay.ts | 3 ++- .../src/detectSqlFilterBehaviour.ts | 12 --------- packages/filterparser/src/index.ts | 1 - .../filterparser/src/parserFilter.test.ts | 4 +-- .../tools/src/detectSqlFilterBehaviour.ts | 17 ++++++++++++ packages/tools/src/driverBase.ts | 4 +++ .../src/filterBehaviours.ts} | 21 ++++++++++----- packages/tools/src/index.ts | 2 ++ packages/types/engines.d.ts | 7 +++-- .../web/src/datagrid/DataFilterControl.svelte | 5 ++-- packages/web/src/datagrid/DataGrid.svelte | 2 -- packages/web/src/datagrid/DataGridCore.svelte | 9 ++++--- packages/web/src/datagrid/JslDataGrid.svelte | 1 - .../web/src/designer/DesignerQueryDumper.ts | 4 +-- .../web/src/designer/DesignerTable.svelte | 4 +-- packages/web/src/designer/designerTools.ts | 6 ++--- .../src/elements/QueryDesignColumns.svelte | 4 +-- .../src/formview/FormViewFilterColumn.svelte | 24 ++++++++--------- .../web/src/formview/FormViewFilters.svelte | 2 -- packages/web/src/modals/SetFilterModal.svelte | 10 ++++--- .../src/modals/SetFilterModal_Select.svelte | 1 - .../src/frontend/driver.js | 4 +++ 24 files changed, 105 insertions(+), 76 deletions(-) delete mode 100644 packages/filterparser/src/detectSqlFilterBehaviour.ts create mode 100644 packages/tools/src/detectSqlFilterBehaviour.ts rename packages/{filterparser/src/filterTypes.ts => tools/src/filterBehaviours.ts} (68%) diff --git a/packages/datalib/src/CollectionGridDisplay.ts b/packages/datalib/src/CollectionGridDisplay.ts index 6af931bb..572341c8 100644 --- a/packages/datalib/src/CollectionGridDisplay.ts +++ b/packages/datalib/src/CollectionGridDisplay.ts @@ -2,6 +2,7 @@ import _ from 'lodash'; import { GridDisplay, ChangeCacheFunc, ChangeConfigFunc, DisplayColumn } from './GridDisplay'; import type { EngineDriver, ViewInfo, ColumnInfo, CollectionInfo } from 'dbgate-types'; import { GridConfig, GridCache } from './GridConfig'; +import { mongoFilterBehaviour, standardFilterBehaviours } from 'dbgate-tools'; function getObjectKeys(obj) { if (_.isArray(obj)) { @@ -52,7 +53,7 @@ function getColumnsForObject(basePath, obj, res: any[], display) { } } -function getDisplayColumn(basePath, columnName, display) { +function getDisplayColumn(basePath, columnName, display: CollectionGridDisplay) { const uniquePath = [...basePath, columnName]; const uniqueName = uniquePath.join('.'); return { @@ -62,7 +63,7 @@ function getDisplayColumn(basePath, columnName, display) { uniquePath, isStructured: true, parentHeaderText: createHeaderText(basePath), - filterType: 'mongo', + filterBehaviour: display?.driver?.getFilterBehaviour(null, standardFilterBehaviours) ?? mongoFilterBehaviour, pureName: display.collection?.pureName, schemaName: display.collection?.schemaName, }; @@ -95,7 +96,7 @@ export class CollectionGridDisplay extends GridDisplay { cache: GridCache, setCache: ChangeCacheFunc, loadedRows, - changeSet, + changeSet, readOnly = false ) { super(config, setConfig, cache, setCache, driver); diff --git a/packages/datalib/src/GridDisplay.ts b/packages/datalib/src/GridDisplay.ts index 84f031af..5b4d49a7 100644 --- a/packages/datalib/src/GridDisplay.ts +++ b/packages/datalib/src/GridDisplay.ts @@ -10,12 +10,13 @@ import type { CollectionInfo, SqlDialect, ViewInfo, + FilterBehaviour, } from 'dbgate-types'; -import { parseFilter, getFilterType } from 'dbgate-filterparser'; +import { parseFilter } from 'dbgate-filterparser'; import { filterName } from 'dbgate-tools'; import { ChangeSetFieldDefinition, ChangeSetRowDefinition } from './ChangeSet'; import { Expression, Select, treeToSql, dumpSqlSelect, Condition, CompoudCondition } from 'dbgate-sqltree'; -import { isTypeLogical } from 'dbgate-tools'; +import { isTypeLogical, standardFilterBehaviours, detectSqlFilterBehaviour, stringFilterBehaviour } from 'dbgate-tools'; export interface DisplayColumn { schemaName: string; @@ -33,7 +34,7 @@ export interface DisplayColumn { isChecked?: boolean; hintColumnNames?: string[]; dataType?: string; - filterType?: boolean; + filterBehaviour?: FilterBehaviour; isStructured?: boolean; } @@ -92,7 +93,7 @@ export abstract class GridDisplay { isLoadedCorrectly = true; supportsReload = false; isDynamicStructure = false; - filterTypeOverride = null; + filterBehaviourOverride = null; setColumnVisibility(uniquePath: string[], isVisible: boolean) { const uniqueName = uniquePath.join('.'); @@ -192,7 +193,11 @@ export abstract class GridDisplay { const column = displayedColumnInfo[uniqueName]; if (!column) continue; try { - const condition = parseFilter(filter, getFilterType(column.dataType)); + const condition = parseFilter( + filter, + this.driver?.getFilterBehaviour(column.dataType, standardFilterBehaviours) ?? + detectSqlFilterBehaviour(column.dataType) + ); if (condition) { conditions.push( _.cloneDeepWith(condition, (expr: Expression) => { @@ -220,7 +225,7 @@ export abstract class GridDisplay { }; for (const column of this.baseTableOrView.columns) { try { - const condition = parseFilter(this.config.multiColumnFilter, getFilterType(column.dataType)); + const condition = parseFilter(this.config.multiColumnFilter, detectSqlFilterBehaviour(column.dataType)); if (condition) { orCondition.conditions.push( _.cloneDeepWith(condition, (expr: Expression) => { @@ -748,10 +753,12 @@ export abstract class GridDisplay { for (const name in filters) { const column = this.isDynamicStructure ? null : this.columns.find(x => x.columnName == name); if (!this.isDynamicStructure && !column) continue; - const filterType = - this.filterTypeOverride ?? (this.isDynamicStructure ? 'mongo' : getFilterType(column.dataType)); + const filterBehaviour = + this.filterBehaviourOverride ?? + this.driver?.getFilterBehaviour(column.dataType, standardFilterBehaviours) ?? + detectSqlFilterBehaviour(column.dataType); try { - const condition = parseFilter(filters[name], filterType); + const condition = parseFilter(filters[name], filterBehaviour); const replaced = _.cloneDeepWith(condition, (expr: Expression) => { if (expr.exprType == 'placeholder') return { @@ -766,7 +773,7 @@ export abstract class GridDisplay { } if (this.config.multiColumnFilter) { - const placeholderCondition = parseFilter(this.config.multiColumnFilter, 'string'); + const placeholderCondition = parseFilter(this.config.multiColumnFilter, stringFilterBehaviour); if (placeholderCondition) { conditions.push({ conditionType: 'anyColumnPass', diff --git a/packages/datalib/src/JslGridDisplay.ts b/packages/datalib/src/JslGridDisplay.ts index 030471be..99149c99 100644 --- a/packages/datalib/src/JslGridDisplay.ts +++ b/packages/datalib/src/JslGridDisplay.ts @@ -2,6 +2,7 @@ import _ from 'lodash'; import { GridDisplay, ChangeCacheFunc, ChangeConfigFunc } from './GridDisplay'; import { GridConfig, GridCache } from './GridConfig'; import { analyseCollectionDisplayColumns } from './CollectionGridDisplay'; +import { evalFilterBehaviour } from 'dbgate-tools'; export class JslGridDisplay extends GridDisplay { constructor( @@ -22,7 +23,7 @@ export class JslGridDisplay extends GridDisplay { this.sortable = true; this.supportsReload = supportsReload; this.isDynamicStructure = isDynamicStructure; - this.filterTypeOverride = 'eval'; + this.filterBehaviourOverride = evalFilterBehaviour; this.editable = editable; this.editableStructure = editable ? structure : null; diff --git a/packages/filterparser/src/detectSqlFilterBehaviour.ts b/packages/filterparser/src/detectSqlFilterBehaviour.ts deleted file mode 100644 index c6156324..00000000 --- a/packages/filterparser/src/detectSqlFilterBehaviour.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { isTypeNumber, isTypeString, isTypeLogical, isTypeDateTime } from 'dbgate-tools'; -import { FilterBehaviour } from 'dbgate-types'; -import { DatetimeFilterBehaviour, LogicalFilterBehaviour, NumberFilterBehaviour, StringFilterBehaviour } from './filterTypes'; - -export function detectSqlFilterType(dataType: string): FilterBehaviour { - if (!dataType) return StringFilterBehaviour; - if (isTypeNumber(dataType)) return NumberFilterBehaviour; - if (isTypeString(dataType)) return StringFilterBehaviour; - if (isTypeLogical(dataType)) return LogicalFilterBehaviour; - if (isTypeDateTime(dataType)) return DatetimeFilterBehaviour; - return StringFilterBehaviour; -} diff --git a/packages/filterparser/src/index.ts b/packages/filterparser/src/index.ts index 40d478b4..6c894f8c 100644 --- a/packages/filterparser/src/index.ts +++ b/packages/filterparser/src/index.ts @@ -1,3 +1,2 @@ export * from './parseFilter'; -export * from './detectSqlFilterBehaviour'; export * from './filterTool'; diff --git a/packages/filterparser/src/parserFilter.test.ts b/packages/filterparser/src/parserFilter.test.ts index 7ae819f9..d1df5348 100644 --- a/packages/filterparser/src/parserFilter.test.ts +++ b/packages/filterparser/src/parserFilter.test.ts @@ -1,8 +1,8 @@ const { parseFilter } = require('./parseFilter'); -const { StringFilterType } = require('./filterTypes'); +const { stringFilterBehaviour } = require('dbgate-tools'); test('parse string', () => { - const ast = parseFilter('"123"', StringFilterType); + const ast = parseFilter('"123"', stringFilterBehaviour); console.log(JSON.stringify(ast)); expect(ast).toEqual({ conditionType: 'like', diff --git a/packages/tools/src/detectSqlFilterBehaviour.ts b/packages/tools/src/detectSqlFilterBehaviour.ts new file mode 100644 index 00000000..a219cf34 --- /dev/null +++ b/packages/tools/src/detectSqlFilterBehaviour.ts @@ -0,0 +1,17 @@ +import { FilterBehaviour } from 'dbgate-types'; +import { + datetimeFilterBehaviour, + logicalFilterBehaviour, + numberFilterBehaviour, + stringFilterBehaviour, +} from './filterBehaviours'; +import { isTypeDateTime, isTypeLogical, isTypeNumber, isTypeString } from './commonTypeParser'; + +export function detectSqlFilterBehaviour(dataType: string): FilterBehaviour { + if (!dataType) return stringFilterBehaviour; + if (isTypeNumber(dataType)) return numberFilterBehaviour; + if (isTypeString(dataType)) return stringFilterBehaviour; + if (isTypeLogical(dataType)) return logicalFilterBehaviour; + if (isTypeDateTime(dataType)) return datetimeFilterBehaviour; + return stringFilterBehaviour; +} diff --git a/packages/tools/src/driverBase.ts b/packages/tools/src/driverBase.ts index e3ea86f9..1517269c 100644 --- a/packages/tools/src/driverBase.ts +++ b/packages/tools/src/driverBase.ts @@ -3,6 +3,7 @@ import { SqlDumper } from './SqlDumper'; import { splitQuery } from 'dbgate-query-splitter'; import { dumpSqlSelect } from 'dbgate-sqltree'; import { EngineDriver, QueryResult, RunScriptOptions } from 'dbgate-types'; +import { detectSqlFilterBehaviour } from './detectSqlFilterBehaviour'; const dialect = { limitSelect: true, @@ -150,4 +151,7 @@ export const driverBase = { showConnectionField: (field, values) => false, showConnectionTab: field => true, getAccessTokenFromAuth: async (connection, req) => null, + getFilterBehaviour(dataType: string, standardFilterBehaviours) { + return detectSqlFilterBehaviour(dataType); + }, }; diff --git a/packages/filterparser/src/filterTypes.ts b/packages/tools/src/filterBehaviours.ts similarity index 68% rename from packages/filterparser/src/filterTypes.ts rename to packages/tools/src/filterBehaviours.ts index 8cc5c794..ac2cc2ce 100644 --- a/packages/filterparser/src/filterTypes.ts +++ b/packages/tools/src/filterBehaviours.ts @@ -1,6 +1,6 @@ import { FilterBehaviour } from 'dbgate-types'; -export const NumberFilterBehaviour: FilterBehaviour = { +export const numberFilterBehaviour: FilterBehaviour = { compilerType: 'sqlTree', supportEquals: true, supportNumberLikeComparison: true, @@ -10,7 +10,7 @@ export const NumberFilterBehaviour: FilterBehaviour = { allowNumberToken: true, }; -export const StringFilterBehaviour: FilterBehaviour = { +export const stringFilterBehaviour: FilterBehaviour = { compilerType: 'sqlTree', supportEquals: true, supportStringInclusion: true, @@ -23,14 +23,14 @@ export const StringFilterBehaviour: FilterBehaviour = { allowHexString: true, }; -export const LogicalFilterBehaviour: FilterBehaviour = { +export const logicalFilterBehaviour: FilterBehaviour = { compilerType: 'sqlTree', supportBooleanValues: true, supportNullTesting: true, supportSqlCondition: true, }; -export const DatetimeFilterBehaviour: FilterBehaviour = { +export const datetimeFilterBehaviour: FilterBehaviour = { compilerType: 'sqlTree', supportNullTesting: true, supportSqlCondition: true, @@ -38,7 +38,7 @@ export const DatetimeFilterBehaviour: FilterBehaviour = { supportDatetimeComparison: true, }; -export const MongoFilterBehaviour: FilterBehaviour = { +export const mongoFilterBehaviour: FilterBehaviour = { compilerType: 'mongoCondition', supportEquals: true, supportArrayTesting: true, @@ -48,7 +48,7 @@ export const MongoFilterBehaviour: FilterBehaviour = { supportExistsTesting: true, }; -export const EvalFilterBehaviour: FilterBehaviour = { +export const evalFilterBehaviour: FilterBehaviour = { compilerType: 'sqlTree', supportEquals: true, supportStringInclusion: true, @@ -58,3 +58,12 @@ export const EvalFilterBehaviour: FilterBehaviour = { allowStringToken: true, }; + +export const standardFilterBehaviours = { + numberFilterBehaviour, + stringFilterBehaviour, + logicalFilterBehaviour, + datetimeFilterBehaviour, + mongoFilterBehaviour, + evalFilterBehaviour, +}; diff --git a/packages/tools/src/index.ts b/packages/tools/src/index.ts index 69e972ca..900f7aeb 100644 --- a/packages/tools/src/index.ts +++ b/packages/tools/src/index.ts @@ -21,3 +21,5 @@ export * from './preloadedRowsTools'; export * from './ScriptWriter'; export * from './getLogger'; export * from './getConnectionLabel'; +export * from './detectSqlFilterBehaviour'; +export * from './filterBehaviours'; diff --git a/packages/types/engines.d.ts b/packages/types/engines.d.ts index 7b8984fd..629b49b2 100644 --- a/packages/types/engines.d.ts +++ b/packages/types/engines.d.ts @@ -72,7 +72,11 @@ export interface ServerSummary { databases: ServerSummaryDatabase[]; } -export interface EngineDriver { +export interface FilterBehaviourProvider { + getFilterBehaviour(dataType: string, standardFilterBehaviours: { string: FilterBehaviour }): FilterBehaviour; +} + +export interface EngineDriver extends FilterBehaviourProvider { engine: string; title: string; defaultPort?: number; @@ -154,7 +158,6 @@ export interface EngineDriver { getRedirectAuthUrl(connection, options): Promise<{ url: string; sid: string }>; getAuthTokenFromCode(connection, options): Promise; getAccessTokenFromAuth(connection, req): Promise; - getFilterType(dataType: string): FilterBehaviour; analyserClass?: any; dumperClass?: any; diff --git a/packages/web/src/datagrid/DataFilterControl.svelte b/packages/web/src/datagrid/DataFilterControl.svelte index 2dfcd5e8..0e71504e 100644 --- a/packages/web/src/datagrid/DataFilterControl.svelte +++ b/packages/web/src/datagrid/DataFilterControl.svelte @@ -19,7 +19,6 @@ import ValueLookupModal from '../modals/ValueLookupModal.svelte'; export let isReadOnly = false; - export let filterType; export let filterBehaviour; export let filter; export let setFilter; @@ -51,7 +50,7 @@ $: if (onGetReference && domInput) onGetReference(domInput); function openFilterWindow(condition1) { - showModal(SetFilterModal, { condition1, filterType, onFilter: setFilter }); + showModal(SetFilterModal, { condition1, filterBehaviour, onFilter: setFilter }); } const filterMultipleValues = () => { @@ -246,7 +245,7 @@ isOk = false; isError = false; if (value) { - parseFilter(value, filterType); + parseFilter(value, filterBehaviour); isOk = true; } } catch (err) { diff --git a/packages/web/src/datagrid/DataGrid.svelte b/packages/web/src/datagrid/DataGrid.svelte index d3a0d04a..66e96ff8 100644 --- a/packages/web/src/datagrid/DataGrid.svelte +++ b/packages/web/src/datagrid/DataGrid.svelte @@ -78,7 +78,6 @@ export let display; export let changeSetState; export let dispatchChangeSet; - export let useEvalFilters = false; export let isDetailView = false; export let showReferences = false; @@ -184,7 +183,6 @@ {...$$props} {managerSize} {isDynamicStructure} - {useEvalFilters} {isFormView} {hasMultiColumnFilter} driver={display?.driver} diff --git a/packages/web/src/datagrid/DataGridCore.svelte b/packages/web/src/datagrid/DataGridCore.svelte index 2ab4edb9..5d03eb85 100644 --- a/packages/web/src/datagrid/DataGridCore.svelte +++ b/packages/web/src/datagrid/DataGridCore.svelte @@ -343,13 +343,13 @@ @@ -51,7 +49,7 @@ display.setFilter(uniqueName, value)} {driver} diff --git a/packages/web/src/formview/FormViewFilters.svelte b/packages/web/src/formview/FormViewFilters.svelte index 18aca5bc..990241ce 100644 --- a/packages/web/src/formview/FormViewFilters.svelte +++ b/packages/web/src/formview/FormViewFilters.svelte @@ -20,7 +20,6 @@ export let pureName; export let isDynamicStructure; - export let useEvalFilters; export let isFormView; export let hasMultiColumnFilter; @@ -93,7 +92,6 @@ {#each allFilterNames as uniqueName} { return condition != 'NULL' && condition != 'NOT NULL' && condition != 'EXISTS' && condition != 'NOT EXISTS'; @@ -24,7 +24,9 @@ if (!value) return null; if (condition == 'sql') return `{${value}}`; if (condition == 'sqlRight') return `{$$ ${value}}`; - if (filterType == 'string') return `${condition}"${value}"`; + if (filterBehaviour.allowStringToken) { + return `${condition}"${value}"`; + } return `${condition}${value}`; }; @@ -48,7 +50,7 @@
Show rows where
- +
@@ -66,7 +68,7 @@
- +
diff --git a/packages/web/src/modals/SetFilterModal_Select.svelte b/packages/web/src/modals/SetFilterModal_Select.svelte index ffec3507..dd4b54b1 100644 --- a/packages/web/src/modals/SetFilterModal_Select.svelte +++ b/packages/web/src/modals/SetFilterModal_Select.svelte @@ -2,7 +2,6 @@ import FormSelectFieldRaw from '../forms/FormSelectFieldRaw.svelte'; export let name; - export let filterType; export let filterBehaviour; function getOptions() { diff --git a/plugins/dbgate-plugin-mongo/src/frontend/driver.js b/plugins/dbgate-plugin-mongo/src/frontend/driver.js index 4ad54613..4945c19e 100644 --- a/plugins/dbgate-plugin-mongo/src/frontend/driver.js +++ b/plugins/dbgate-plugin-mongo/src/frontend/driver.js @@ -93,6 +93,10 @@ const driver = { } return res; }, + + getFilterBehaviour(dataType, standardFilterBehaviours) { + return standardFilterBehaviours.mongoFilterBehaviour; + }, }; module.exports = driver;