diff --git a/packages/engines/default/DatabaseAnalyser.js b/packages/engines/default/DatabaseAnalyser.js index 9fee5ea77..50457e8d7 100644 --- a/packages/engines/default/DatabaseAnalyser.js +++ b/packages/engines/default/DatabaseAnalyser.js @@ -89,6 +89,7 @@ DatabaseAnalyser.createEmptyStructure = () => ({ functions: [], procedures: [], triggers: [], + schemas: [], }); DatabaseAnalyser.byTableFilter = (table) => (x) => x.pureName == table.pureName && x.schemaName == x.schemaName; diff --git a/packages/engines/mssql/MsSqlAnalyser.js b/packages/engines/mssql/MsSqlAnalyser.js index 17cb98f20..d96886290 100644 --- a/packages/engines/mssql/MsSqlAnalyser.js +++ b/packages/engines/mssql/MsSqlAnalyser.js @@ -168,7 +168,7 @@ class MsSqlAnalyser extends DatabaseAnalyser { if (this.singleObjectFilter) { const { typeField } = this.singleObjectFilter; if (!this.singleObjectId) return null; - if (!filterIdObjects.includes(typeField)) return null; + if (!filterIdObjects || !filterIdObjects.includes(typeField)) return null; return res.replace('=[OBJECT_ID_CONDITION]', ` = ${this.singleObjectId}`); } if (!this.modifications || !filterIdObjects || this.modifications.length == 0) { @@ -202,6 +202,9 @@ class MsSqlAnalyser extends DatabaseAnalyser { const columnsRows = await this.driver.query(this.pool, this.createQuery('columns', ['tables'])); const pkColumnsRows = await this.driver.query(this.pool, this.createQuery('primaryKeys', ['tables'])); const fkColumnsRows = await this.driver.query(this.pool, this.createQuery('foreignKeys', ['tables'])); + const schemaRows = await this.driver.query(this.pool, this.createQuery('getSchemas')); + + const schemas = schemaRows.rows; const sqlCodeRows = await this.driver.query( this.pool, @@ -265,6 +268,7 @@ class MsSqlAnalyser extends DatabaseAnalyser { views, procedures, functions, + schemas, }); } diff --git a/packages/engines/mssql/sql/getSchemas.js b/packages/engines/mssql/sql/getSchemas.js new file mode 100644 index 000000000..a7cb0a4de --- /dev/null +++ b/packages/engines/mssql/sql/getSchemas.js @@ -0,0 +1 @@ +module.exports = `select schema_id as objectId, name as schemaName from sys.schemas`; diff --git a/packages/engines/mssql/sql/index.js b/packages/engines/mssql/sql/index.js index 6165eaee1..cb40e88a5 100644 --- a/packages/engines/mssql/sql/index.js +++ b/packages/engines/mssql/sql/index.js @@ -7,6 +7,7 @@ const loadSqlCode = require('./loadSqlCode'); const views = require('./views'); const programmables = require('./programmables'); const viewColumns = require('./viewColumns'); +const getSchemas = require('./getSchemas'); module.exports = { columns, @@ -18,4 +19,5 @@ module.exports = { views, programmables, viewColumns, + getSchemas, }; diff --git a/packages/types/dbinfo.d.ts b/packages/types/dbinfo.d.ts index 4f174c761..46f50158e 100644 --- a/packages/types/dbinfo.d.ts +++ b/packages/types/dbinfo.d.ts @@ -71,10 +71,16 @@ export interface FunctionInfo extends SqlObjectInfo {} export interface TriggerInfo extends SqlObjectInfo {} +export interface SchemaInfo { + objectId?: string; + schemaName: string; +} + export interface DatabaseInfo { tables: TableInfo[]; views: ViewInfo[]; procedures: ProcedureInfo[]; functions: FunctionInfo[]; triggers: TriggerInfo[]; + schemas: SchemaInfo[]; } diff --git a/packages/web/src/appobj/databaseObjectAppObject.js b/packages/web/src/appobj/databaseObjectAppObject.js index 8d21f1062..1366674b5 100644 --- a/packages/web/src/appobj/databaseObjectAppObject.js +++ b/packages/web/src/appobj/databaseObjectAppObject.js @@ -114,7 +114,8 @@ function Menu({ data, makeAppObj, setOpenedTabs, showModal }) { sourceStorageType: 'database', sourceConnectionId: data.conid, sourceDatabaseName: data.database, - sourceTables: [fullNameToString(data)], + sourceSchemaName: data.schemaName, + sourceTables: [data.pureName], }} /> )); diff --git a/packages/web/src/datagrid/DataGridCore.js b/packages/web/src/datagrid/DataGridCore.js index e884e03ae..db8207579 100644 --- a/packages/web/src/datagrid/DataGridCore.js +++ b/packages/web/src/datagrid/DataGridCore.js @@ -604,7 +604,8 @@ export default function DataGridCore(props) { sourceStorageType: 'database', sourceConnectionId: conid, sourceDatabaseName: database, - sourceTables: display.baseTable ? [fullNameToString(display.baseTable)] : [], + sourceSchemaName: display.baseTable && display.baseTable.schemaName, + sourceTables: display.baseTable ? [display.baseTable.pureName] : [], }} /> )); diff --git a/packages/web/src/impexp/ImportExportConfigurator.js b/packages/web/src/impexp/ImportExportConfigurator.js index 5be22e7bb..b21a8ba2c 100644 --- a/packages/web/src/impexp/ImportExportConfigurator.js +++ b/packages/web/src/impexp/ImportExportConfigurator.js @@ -11,9 +11,12 @@ import { FormConnectionSelect, FormDatabaseSelect, FormTablesSelect, + FormSelectField, + FormSchemaSelect, } from '../utility/forms'; import { useConnectionList, useDatabaseList } from '../utility/metadataLoaders'; import TableControl, { TableColumn } from '../utility/TableControl'; +import { TextField, SelectField } from '../utility/inputs'; const Container = styled.div``; @@ -66,9 +69,9 @@ function DatabaseSelector() { ); } -function SourceTargetConfig({ direction, storageTypeField, connectionIdField, databaseNameField, tablesField }) { +function SourceTargetConfig({ direction, storageTypeField, connectionIdField, databaseNameField, schemaNameField,tablesField }) { const types = [ - { value: 'database', label: 'Database', directions: ['source'] }, + { value: 'database', label: 'Database', directions: ['source', 'target'] }, { value: 'csv', label: 'CSV file(s)', directions: ['target'] }, { value: 'jsonl', label: 'JSON lines file(s)', directions: ['target'] }, ]; @@ -84,10 +87,12 @@ function SourceTargetConfig({ direction, storageTypeField, connectionIdField, da + + {direction == 'source' && ( <> - + )} @@ -99,6 +104,9 @@ function SourceTargetConfig({ direction, storageTypeField, connectionIdField, da export default function ImportExportConfigurator() { const { values } = useFormikContext(); const sources = values.sourceTables; + const getActionOptions = ()=>{ + + } const actionOptions = [ { label: 'Create file', @@ -125,6 +133,7 @@ export default function ImportExportConfigurator() { storageTypeField="sourceStorageType" connectionIdField="sourceConnectionId" databaseNameField="sourceDatabaseName" + schemaNameField="sourceSchemaName" tablesField="sourceTables" /> - {/* + row} /> - } - /> - */} + } /> + } /> + ); } diff --git a/packages/web/src/impexp/createImpExpScript.js b/packages/web/src/impexp/createImpExpScript.js index a2496a9b5..e22aaf3da 100644 --- a/packages/web/src/impexp/createImpExpScript.js +++ b/packages/web/src/impexp/createImpExpScript.js @@ -14,7 +14,7 @@ export default async function createImpExpScript(values) { const connection = await getConnectionInfo({ conid: values.sourceConnectionId }); const driver = engines(connection); - const fullName = fullNameFromString(table); + const fullName = { schemaName: values.sourceSchemaName, pureName: table }; script.assign(sourceVar, 'queryReader', { connection: { ..._.pick(connection, ['server', 'engine', 'user', 'password', 'port']), diff --git a/packages/web/src/utility/forms.js b/packages/web/src/utility/forms.js index 776d9cc09..d7b52a727 100644 --- a/packages/web/src/utility/forms.js +++ b/packages/web/src/utility/forms.js @@ -50,7 +50,7 @@ export function FormSelectFieldRaw({ children, ...other }) { ); } -export function FormSelectField({ label, children, ...other }) { +export function FormSelectField({ label, children = null, ...other }) { return ( {label} @@ -138,16 +138,34 @@ export function FormDatabaseSelect({ conidName, name }) { return ; } -export function FormTablesSelect({ conidName, databaseName, name }) { +export function FormSchemaSelect({ conidName, databaseName, name }) { + const { values } = useFormikContext(); + const dbinfo = useDatabaseInfo({ conid: values[conidName], database: values[databaseName] }); + const schemaOptions = React.useMemo( + () => + ((dbinfo && dbinfo.schemas) || []).map((schema) => ({ + value: schema.schemaName, + label: schema.schemaName, + })), + [dbinfo] + ); + + if (schemaOptions.length == 0) return
Not available
; + return ; +} + +export function FormTablesSelect({ conidName, databaseName, schemaName, name }) { const { values } = useFormikContext(); const dbinfo = useDatabaseInfo({ conid: values[conidName], database: values[databaseName] }); const tablesOptions = React.useMemo( () => - [...((dbinfo && dbinfo.tables) || []), ...((dbinfo && dbinfo.views) || [])].map((x) => ({ - value: fullNameToString(x), - label: x.pureName, - })), - [dbinfo] + [...((dbinfo && dbinfo.tables) || []), ...((dbinfo && dbinfo.views) || [])] + .filter((x) => !values[schemaName] || x.schemaName == values[schemaName]) + .map((x) => ({ + value: x.pureName, + label: x.pureName, + })), + [dbinfo, values[schemaName]] ); if (tablesOptions.length == 0) return
Not available
; diff --git a/packages/web/src/utility/inputs.js b/packages/web/src/utility/inputs.js index 06ba97d25..f352886f3 100644 --- a/packages/web/src/utility/inputs.js +++ b/packages/web/src/utility/inputs.js @@ -4,6 +4,15 @@ export function TextField({ editorRef = undefined, ...other }) { return ; } -export function SelectField({ children, ...other }) { - return ; +export function SelectField({ children = null, options = [], ...other }) { + return ( + + ); }