diff --git a/packages/api/src/controllers/databaseConnections.js b/packages/api/src/controllers/databaseConnections.js index 1205dfc87..f2bedc4b4 100644 --- a/packages/api/src/controllers/databaseConnections.js +++ b/packages/api/src/controllers/databaseConnections.js @@ -92,6 +92,13 @@ module.exports = { return res; }, + collectionData_meta: 'post', + async collectionData({ conid, database, options }) { + const opened = await this.ensureOpened(conid, database); + const res = await this.sendRequest(opened, { msgtype: 'collectionData', options }); + return res; + }, + status_meta: 'get', async status({ conid, database }) { const existing = this.opened.find(x => x.conid == conid && x.database == database); diff --git a/packages/api/src/controllers/metadata.js b/packages/api/src/controllers/metadata.js index 1bcfe90ae..961d749cb 100644 --- a/packages/api/src/controllers/metadata.js +++ b/packages/api/src/controllers/metadata.js @@ -17,7 +17,7 @@ module.exports = { listObjects_meta: 'get', async listObjects({ conid, database }) { const opened = await databaseConnections.ensureOpened(conid, database); - const types = ['tables', 'views', 'procedures', 'functions', 'triggers']; + const types = ['tables', 'collections', 'views', 'procedures', 'functions', 'triggers']; return types.reduce( (res, type) => ({ ...res, diff --git a/packages/api/src/proc/databaseConnectionProcess.js b/packages/api/src/proc/databaseConnectionProcess.js index 3aee1c4f0..beed47085 100644 --- a/packages/api/src/proc/databaseConnectionProcess.js +++ b/packages/api/src/proc/databaseConnectionProcess.js @@ -94,6 +94,17 @@ async function handleQueryData({ msgid, sql }) { } } +async function handleCollectionData({ msgid, options }) { + await waitConnected(); + const driver = requireEngineDriver(storedConnection); + try { + const result = await driver.readCollection(systemConnection, options); + process.send({ msgtype: 'response', msgid, result }); + } catch (err) { + process.send({ msgtype: 'response', msgid, errorMessage: err.message }); + } +} + async function handleSqlPreview({ msgid, objects, options }) { await waitConnected(); const driver = requireEngineDriver(storedConnection); @@ -129,6 +140,7 @@ function handlePing() { const messageHandlers = { connect: handleConnect, queryData: handleQueryData, + collectionData: handleCollectionData, sqlPreview: handleSqlPreview, ping: handlePing, // runCommand: handleRunCommand, diff --git a/packages/datalib/src/CollectionGridDisplay.ts b/packages/datalib/src/CollectionGridDisplay.ts new file mode 100644 index 000000000..85c9af37d --- /dev/null +++ b/packages/datalib/src/CollectionGridDisplay.ts @@ -0,0 +1,46 @@ +import _ from 'lodash'; +import { GridDisplay, ChangeCacheFunc, ChangeConfigFunc } from './GridDisplay'; +import { EngineDriver, ViewInfo, ColumnInfo, CollectionInfo } from 'dbgate-types'; +import { GridConfig, GridCache } from './GridConfig'; + +export class CollectionGridDisplay extends GridDisplay { + constructor( + public collection: CollectionInfo, + driver: EngineDriver, + config: GridConfig, + setConfig: ChangeConfigFunc, + cache: GridCache, + setCache: ChangeCacheFunc + ) { + super(config, setConfig, cache, setCache, driver); + this.columns = []; + this.filterable = true; + this.sortable = true; + this.editable = false; + this.supportsReload = true; + } + + // getDisplayColumns(view: ViewInfo) { + // return ( + // view?.columns + // ?.map(col => this.getDisplayColumn(view, col)) + // ?.map(col => ({ + // ...col, + // isChecked: this.isColumnChecked(col), + // })) || [] + // ); + // } + + // getDisplayColumn(view: ViewInfo, col: ColumnInfo) { + // const uniquePath = [col.columnName]; + // const uniqueName = uniquePath.join('.'); + // return { + // ...col, + // pureName: view.pureName, + // schemaName: view.schemaName, + // headerText: col.columnName, + // uniqueName, + // uniquePath, + // }; + // } +} diff --git a/packages/tools/src/DatabaseAnalyser.ts b/packages/tools/src/DatabaseAnalyser.ts index 0667fa930..020ac39da 100644 --- a/packages/tools/src/DatabaseAnalyser.ts +++ b/packages/tools/src/DatabaseAnalyser.ts @@ -49,7 +49,7 @@ export class DatabaseAnalyser { } const res = {}; - for (const field of ['tables', 'views', 'functions', 'procedures', 'triggers']) { + for (const field of ['tables', 'collections', 'views', 'functions', 'procedures', 'triggers']) { const removedIds = this.modifications .filter(x => x.action == 'remove' && x.objectTypeField == field) .map(x => extractObjectId(x)); @@ -78,6 +78,7 @@ export class DatabaseAnalyser { static createEmptyStructure(): DatabaseInfo { return { tables: [], + collections: [], views: [], functions: [], procedures: [], diff --git a/packages/tools/src/structureTools.ts b/packages/tools/src/structureTools.ts index 6aac3291d..38d1c45ea 100644 --- a/packages/tools/src/structureTools.ts +++ b/packages/tools/src/structureTools.ts @@ -56,6 +56,10 @@ function fillTableExtendedInfo(db: DatabaseInfo): DatabaseInfo { constraintType: 'unique', })), })), + collections: (db.collections || []).map(obj => ({ + ...obj, + objectTypeField: 'collections', + })), views: (db.views || []).map(obj => ({ ...obj, objectTypeField: 'views', diff --git a/packages/types/dbinfo.d.ts b/packages/types/dbinfo.d.ts index 5805ac534..37533de97 100644 --- a/packages/types/dbinfo.d.ts +++ b/packages/types/dbinfo.d.ts @@ -74,6 +74,8 @@ export interface TableInfo extends DatabaseObjectInfo { checks?: CheckInfo[]; } +export interface CollectionInfo extends DatabaseObjectInfo {} + export interface ViewInfo extends SqlObjectInfo { columns: ColumnInfo[]; } @@ -91,6 +93,7 @@ export interface SchemaInfo { export interface DatabaseInfoObjects { tables: TableInfo[]; + collections: CollectionInfo[]; views: ViewInfo[]; procedures: ProcedureInfo[]; functions: FunctionInfo[]; diff --git a/packages/types/dialect.d.ts b/packages/types/dialect.d.ts index 00e3387c4..8cd6ecdbe 100644 --- a/packages/types/dialect.d.ts +++ b/packages/types/dialect.d.ts @@ -8,4 +8,5 @@ export interface SqlDialect { explicitDropConstraint?: boolean; anonymousPrimaryKey?: boolean; enableConstraintsPerTable?: boolean; + nosql?: boolean; // mongo } diff --git a/packages/types/engines.d.ts b/packages/types/engines.d.ts index a8e3cc753..52a9ed061 100644 --- a/packages/types/engines.d.ts +++ b/packages/types/engines.d.ts @@ -24,6 +24,14 @@ export interface EngineAuthType { disabledFields: string[]; } +export interface ReadCollectionOptions { + pureName: string; + schemaName?: string; + + countDocuments?: boolean; + skip?: number; + limit?: number; +} export interface EngineDriver { engine: string; title: string; @@ -52,6 +60,7 @@ export interface EngineDriver { dialect: SqlDialect; createDumper(): SqlDumper; getAuthTypes(): EngineAuthType[]; + readCollection(pool: any, options: ReadCollectionOptions): Promise; analyserClass?: any; dumperClass?: any; diff --git a/packages/web/src/appobj/DatabaseObjectAppObject.svelte b/packages/web/src/appobj/DatabaseObjectAppObject.svelte index af678026b..78df55d4d 100644 --- a/packages/web/src/appobj/DatabaseObjectAppObject.svelte +++ b/packages/web/src/appobj/DatabaseObjectAppObject.svelte @@ -4,6 +4,7 @@ const icons = { tables: 'img table', + collections: 'img collection', views: 'img view', procedures: 'img procedure', functions: 'img function', @@ -11,6 +12,7 @@ const defaultTabs = { tables: 'TableDataTab', + collections: 'CollectionDataTab', views: 'ViewDataTab', }; diff --git a/packages/web/src/datagrid/CollectionDataGridCore.svelte b/packages/web/src/datagrid/CollectionDataGridCore.svelte new file mode 100644 index 000000000..62ec9a53c --- /dev/null +++ b/packages/web/src/datagrid/CollectionDataGridCore.svelte @@ -0,0 +1,189 @@ + + + + + diff --git a/packages/web/src/datagrid/DataGrid.svelte b/packages/web/src/datagrid/DataGrid.svelte index a999faf3b..5ba9da4f1 100644 --- a/packages/web/src/datagrid/DataGrid.svelte +++ b/packages/web/src/datagrid/DataGrid.svelte @@ -69,7 +69,7 @@ name="references" height="30%" collapsed={isDetailView} - skip={!showReferences || !display.hasReferences} + skip={!showReferences || !display?.hasReferences} > diff --git a/packages/web/src/datagrid/DataGridCore.svelte b/packages/web/src/datagrid/DataGridCore.svelte index a980cf8ad..520dc14ec 100644 --- a/packages/web/src/datagrid/DataGridCore.svelte +++ b/packages/web/src/datagrid/DataGridCore.svelte @@ -269,6 +269,7 @@ export let isLoadedAll; export let loadedTime; export let changeSetStore; + export let isDynamicStructure = false; // export let generalAllowSave = false; const wheelRowCount = 5; @@ -1025,7 +1026,7 @@ } -{#if !columns || columns.length == 0} +{#if !isDynamicStructure && (!columns || columns.length == 0)} {:else if errorMessage} diff --git a/packages/web/src/icons/FontIcon.svelte b/packages/web/src/icons/FontIcon.svelte index 36f145d97..15b46bd03 100644 --- a/packages/web/src/icons/FontIcon.svelte +++ b/packages/web/src/icons/FontIcon.svelte @@ -92,6 +92,7 @@ 'img database': 'mdi mdi-database color-icon-gold', 'img table': 'mdi mdi-table color-icon-blue', + 'img collection': 'mdi mdi-table color-icon-red', 'img view': 'mdi mdi-table color-icon-magenta', 'img procedure': 'mdi mdi-cog color-icon-blue', 'img function': 'mdi mdi-function-variant', diff --git a/packages/web/src/tabs/CollectionDataTab.svelte b/packages/web/src/tabs/CollectionDataTab.svelte new file mode 100644 index 000000000..5a2f82e9e --- /dev/null +++ b/packages/web/src/tabs/CollectionDataTab.svelte @@ -0,0 +1,49 @@ + + + + + diff --git a/packages/web/src/tabs/index.js b/packages/web/src/tabs/index.js index 331b70860..89e920a17 100644 --- a/packages/web/src/tabs/index.js +++ b/packages/web/src/tabs/index.js @@ -1,4 +1,5 @@ import * as TableDataTab from './TableDataTab.svelte'; +import * as CollectionDataTab from './CollectionDataTab.svelte'; import * as ViewDataTab from './ViewDataTab.svelte'; import * as TableStructureTab from './TableStructureTab.svelte'; import * as QueryTab from './QueryTab.svelte'; @@ -15,6 +16,7 @@ import * as QueryDesignTab from './QueryDesignTab.svelte'; export default { TableDataTab, + CollectionDataTab, ViewDataTab, TableStructureTab, QueryTab, diff --git a/packages/web/src/widgets/DatabaseWidget.svelte b/packages/web/src/widgets/DatabaseWidget.svelte index 1ce47f105..56318bfdf 100644 --- a/packages/web/src/widgets/DatabaseWidget.svelte +++ b/packages/web/src/widgets/DatabaseWidget.svelte @@ -1,16 +1,24 @@ - - - + + diff --git a/packages/web/src/widgets/SqlObjectList.svelte b/packages/web/src/widgets/SqlObjectList.svelte index fa4ef5696..d1bb38871 100644 --- a/packages/web/src/widgets/SqlObjectList.svelte +++ b/packages/web/src/widgets/SqlObjectList.svelte @@ -21,8 +21,10 @@ $: objects = useDatabaseInfo({ conid, database }); $: status = useDatabaseStatus({ conid, database }); + // $: console.log('objects', $objects); + $: objectList = _.flatten( - ['tables', 'views', 'procedures', 'functions'].map(objectTypeField => + ['tables', 'collections', 'views', 'procedures', 'functions'].map(objectTypeField => _.sortBy( (($objects || {})[objectTypeField] || []).map(obj => ({ ...obj, objectTypeField })), ['schemaName', 'pureName'] diff --git a/packages/web/src/widgets/SqlObjectListWrapper.svelte b/packages/web/src/widgets/SqlObjectListWrapper.svelte index ffcf4e115..1c62b4d7d 100644 --- a/packages/web/src/widgets/SqlObjectListWrapper.svelte +++ b/packages/web/src/widgets/SqlObjectListWrapper.svelte @@ -1,7 +1,7 @@