diff --git a/packages/api/src/controllers/databaseConnections.js b/packages/api/src/controllers/databaseConnections.js index eea07817a..c633677a7 100644 --- a/packages/api/src/controllers/databaseConnections.js +++ b/packages/api/src/controllers/databaseConnections.js @@ -151,34 +151,33 @@ module.exports = { return res.result; }, - loadKeys_meta: true, - async loadKeys({ conid, database, root }) { + async loadDataCore(msgtype, {conid, database, ...args}) { const opened = await this.ensureOpened(conid, database); - const res = await this.sendRequest(opened, { msgtype: 'loadKeys', root }); + const res = await this.sendRequest(opened, { msgtype, ...args }); if (res.errorMessage) { console.error(res.errorMessage); } return res.result || null; }, + loadKeys_meta: true, + async loadKeys({ conid, database, root }) { + return this.loadDataCore('loadKeys', { conid, database, root }); + }, + loadKeyInfo_meta: true, async loadKeyInfo({ conid, database, key }) { - const opened = await this.ensureOpened(conid, database); - const res = await this.sendRequest(opened, { msgtype: 'loadKeyInfo', key }); - if (res.errorMessage) { - console.error(res.errorMessage); - } - return res.result || null; + return this.loadDataCore('loadKeyInfo', { conid, database, key }); }, loadKeyTableRange_meta: true, async loadKeyTableRange({ conid, database, key, cursor, count }) { - const opened = await this.ensureOpened(conid, database); - const res = await this.sendRequest(opened, { msgtype: 'loadKeyTableRange', key, cursor, count }); - if (res.errorMessage) { - console.error(res.errorMessage); - } - return res.result || null; + return this.loadDataCore('loadKeyTableRange', { conid, database, key, cursor, count }); + }, + + loadFieldValues_meta: true, + async loadFieldValues({ conid, database, schemaName, pureName, field, search }) { + return this.loadDataCore('loadFieldValues', { conid, database, schemaName, pureName, field, search }); }, callMethod_meta: true, diff --git a/packages/api/src/proc/databaseConnectionProcess.js b/packages/api/src/proc/databaseConnectionProcess.js index da730ba68..b99a8973a 100644 --- a/packages/api/src/proc/databaseConnectionProcess.js +++ b/packages/api/src/proc/databaseConnectionProcess.js @@ -172,59 +172,41 @@ async function handleQueryData({ msgid, sql }) { } } -async function handleCollectionData({ msgid, options }) { +async function handleDriverDataCore(msgid, callMethod) { await waitConnected(); const driver = requireEngineDriver(storedConnection); try { - const result = await driver.readCollection(systemConnection, options); + const result = await callMethod(driver); process.send({ msgtype: 'response', msgid, result }); } catch (err) { process.send({ msgtype: 'response', msgid, errorMessage: err.message }); } } +async function handleCollectionData({ msgid, options }) { + return handleDriverDataCore(msgid, driver => driver.readCollection(systemConnection, options)); +} + async function handleLoadKeys({ msgid, root }) { - await waitConnected(); - const driver = requireEngineDriver(storedConnection); - try { - const result = await driver.loadKeys(systemConnection, root); - process.send({ msgtype: 'response', msgid, result }); - } catch (err) { - process.send({ msgtype: 'response', msgid, errorMessage: err.message }); - } + return handleDriverDataCore(msgid, driver => driver.loadKeys(systemConnection, root)); } async function handleLoadKeyInfo({ msgid, key }) { - await waitConnected(); - const driver = requireEngineDriver(storedConnection); - try { - const result = await driver.loadKeyInfo(systemConnection, key); - process.send({ msgtype: 'response', msgid, result }); - } catch (err) { - process.send({ msgtype: 'response', msgid, errorMessage: err.message }); - } + return handleDriverDataCore(msgid, driver => driver.loadKeyInfo(systemConnection, key)); } async function handleCallMethod({ msgid, method, args }) { - await waitConnected(); - const driver = requireEngineDriver(storedConnection); - try { - const result = await driver.callMethod(systemConnection, method, args); - process.send({ msgtype: 'response', msgid, result }); - } catch (err) { - process.send({ msgtype: 'response', msgid, errorMessage: err.message }); - } + return handleDriverDataCore(msgid, driver => driver.callMethod(systemConnection, method, args)); } async function handleLoadKeyTableRange({ msgid, key, cursor, count }) { - await waitConnected(); - const driver = requireEngineDriver(storedConnection); - try { - const result = await driver.loadKeyTableRange(systemConnection, key, cursor, count); - process.send({ msgtype: 'response', msgid, result }); - } catch (err) { - process.send({ msgtype: 'response', msgid, errorMessage: err.message }); - } + return handleDriverDataCore(msgid, driver => driver.loadKeyTableRange(systemConnection, key, cursor, count)); +} + +async function handleLoadFieldValues({ msgid, schemaName, pureName, field, search }) { + return handleDriverDataCore(msgid, driver => + driver.loadFieldValues(systemConnection, { schemaName, pureName }, field, search) + ); } async function handleUpdateCollection({ msgid, changeSet }) { @@ -300,6 +282,7 @@ const messageHandlers = { ping: handlePing, syncModel: handleSyncModel, generateDeploySql: handleGenerateDeploySql, + loadFieldValues: handleLoadFieldValues, // runCommand: handleRunCommand, }; diff --git a/packages/tools/package.json b/packages/tools/package.json index 6d4a7984b..f86bf9a35 100644 --- a/packages/tools/package.json +++ b/packages/tools/package.json @@ -26,6 +26,7 @@ "devDependencies": { "@types/node": "^13.7.0", "dbgate-types": "^4.1.1", + "dbgate-sqltree": "^4.1.1", "jest": "^24.9.0", "ts-jest": "^25.2.1", "typescript": "^4.4.3" diff --git a/packages/tools/src/driverBase.ts b/packages/tools/src/driverBase.ts index 6618ec48b..2b67ccdde 100644 --- a/packages/tools/src/driverBase.ts +++ b/packages/tools/src/driverBase.ts @@ -1,5 +1,7 @@ +import _compact from 'lodash/compact' import { SqlDumper } from './SqlDumper'; import { splitQuery } from 'dbgate-query-splitter'; +import { dumpSqlSelect } from 'dbgate-sqltree'; const dialect = { limitSelect: true, @@ -51,4 +53,56 @@ export const driverBase = { } return []; }, + async loadFieldValues(pool, name, columnName, search) { + const dmp = this.createDumper(); + const select = { + commandType: 'select', + distinct: true, + topRecords: 100, + + from: { + name, + }, + columns: [ + { + exprType: 'column', + columnName, + alias: 'value', + }, + ], + orderBy: [ + { + exprType: 'column', + columnName, + }, + ], + }; + + if (search) { + const tokens = _compact(search.split(' ').map(x => x.trim())); + if (tokens.length > 0) { + // @ts-ignore + select.where = { + conditionType: 'and', + conditions: tokens.map(token => ({ + conditionType: 'like', + left: { + exprType: 'column', + columnName, + }, + right: { + exprType: 'value', + value: `%${token}%`, + }, + })), + }; + } + } + + // @ts-ignore + dumpSqlSelect(dmp, select); + + const resp = await this.query(pool, dmp.s); + return resp.rows; + }, }; diff --git a/packages/types/engines.d.ts b/packages/types/engines.d.ts index ab60bb2e6..d5529be5c 100644 --- a/packages/types/engines.d.ts +++ b/packages/types/engines.d.ts @@ -79,6 +79,7 @@ export interface EngineDriver { loadKeys(pool, root: string): Promise; loadKeyInfo(pool, key): Promise; loadKeyTableRange(pool, key, cursor, count): Promise; + loadFieldValues(pool: any, name: NamedObjectInfo, field: string, search: string): Promise; analyseFull(pool: any, serverVersion): Promise; analyseIncremental(pool: any, structure: DatabaseInfo, serverVersion): Promise; dialect: SqlDialect; diff --git a/packages/web/src/datagrid/DataFilterControl.svelte b/packages/web/src/datagrid/DataFilterControl.svelte index 2f49ac426..d412059a1 100644 --- a/packages/web/src/datagrid/DataFilterControl.svelte +++ b/packages/web/src/datagrid/DataFilterControl.svelte @@ -266,8 +266,8 @@ class:isOk placeholder="Filter" /> - {#if conid && database && driver && driver?.databaseEngineTypes?.includes('sql')} - {#if foreignKey} + {#if conid && database && driver} + {#if driver?.databaseEngineTypes?.includes('sql') && foreignKey} diff --git a/packages/web/src/modals/ValueLookupModal.svelte b/packages/web/src/modals/ValueLookupModal.svelte index 9ea61f59f..e2d4e3b35 100644 --- a/packages/web/src/modals/ValueLookupModal.svelte +++ b/packages/web/src/modals/ValueLookupModal.svelte @@ -34,64 +34,16 @@ let checkedKeys = []; async function reload() { - const dmp = driver.createDumper(); - const select = { - commandType: 'select', - distinct: true, - topRecords: 100, - - from: { - name: { - schemaName, - pureName, - }, - }, - columns: [ - { - exprType: 'column', - columnName, - }, - ], - orderBy: [ - { - exprType: 'column', - columnName, - }, - ], - }; - - if (search) { - const tokens = _.compact(search.split(' ').map(x => x.trim())); - if (tokens.length > 0) { - // @ts-ignore - select.where = { - conditionType: 'and', - conditions: tokens.map(token => ({ - conditionType: 'like', - left: { - exprType: 'column', - columnName, - }, - right: { - exprType: 'value', - value: `%${token}%`, - }, - })), - }; - } - } - - // @ts-ignore - dumpSqlSelect(dmp, select); - isLoading = true; - const response = await apiCall('database-connections/query-data', { + rows = await apiCall('database-connections/load-field-values', { conid, database, - sql: dmp.s, + search, + schemaName, + pureName, + field: columnName, }); - rows = response.rows; isLoading = false; } @@ -124,7 +76,7 @@ {rows} clickable on:clickrow={e => { - const value = e.detail[columnName]; + const { value } = e.detail; if (multiselect) { if (checkedKeys.includes(value)) checkedKeys = checkedKeys.filter(x => x != value); else checkedKeys = [...checkedKeys, value]; @@ -143,7 +95,7 @@ { fieldName: 'value', header: 'Value', - formatter: row => (row[columnName] == null ? '(NULL)' : row[columnName]), + formatter: row => (row.value == null ? '(NULL)' : row.value), }, ]} > @@ -151,9 +103,9 @@ type="checkbox" let:row slot="1" - checked={checkedKeys.includes(row[columnName])} + checked={checkedKeys.includes(row['value'])} on:change={e => { - const value = row[columnName]; + const value = row['value']; if (e.target.checked) { if (!checkedKeys.includes(value)) checkedKeys = [...checkedKeys, value]; } else {