diff --git a/packages/datalib/src/ChangeSet.ts b/packages/datalib/src/ChangeSet.ts index a9a7011b8..a063bb160 100644 --- a/packages/datalib/src/ChangeSet.ts +++ b/packages/datalib/src/ChangeSet.ts @@ -228,7 +228,7 @@ function changeSetInsertToSql( const table = dbinfo.tables.find(x => x.schemaName == item.schemaName && x.pureName == item.pureName); if (table) { const autoIncCol = table.columns.find(x => x.autoIncrement); - console.log('autoIncCol', autoIncCol); + // console.log('autoIncCol', autoIncCol); if (autoIncCol && fields.find(x => x.targetColumn == autoIncCol.columnName)) { autoInc = true; } @@ -375,7 +375,7 @@ export function getChangeSetInsertedRows(changeSet: ChangeSet, name?: NamedObjec } export function changeSetInsertNewRow(changeSet: ChangeSet, name?: NamedObjectInfo): ChangeSet { - console.log('INSERT', name); + // console.log('INSERT', name); const insertedRows = getChangeSetInsertedRows(changeSet, name); return { ...changeSet, diff --git a/packages/datalib/src/CollectionGridDisplay.ts b/packages/datalib/src/CollectionGridDisplay.ts index 8f54c2f1f..3a1c79c6d 100644 --- a/packages/datalib/src/CollectionGridDisplay.ts +++ b/packages/datalib/src/CollectionGridDisplay.ts @@ -89,10 +89,12 @@ export class CollectionGridDisplay extends GridDisplay { setConfig: ChangeConfigFunc, cache: GridCache, setCache: ChangeCacheFunc, - loadedRows + loadedRows, + changeSet ) { super(config, setConfig, cache, setCache, driver); - this.columns = analyseCollectionDisplayColumns(loadedRows, this); + const changedDocs = _.compact([...changeSet.inserts, ...changeSet.updates].map(chs => chs.document)); + this.columns = analyseCollectionDisplayColumns([...(loadedRows || []), ...changedDocs], this); this.filterable = true; this.sortable = true; this.editable = true; diff --git a/packages/query-splitter/src/options.ts b/packages/query-splitter/src/options.ts index eef5ec884..c32e697ce 100644 --- a/packages/query-splitter/src/options.ts +++ b/packages/query-splitter/src/options.ts @@ -8,6 +8,9 @@ export interface SplitterOptions { allowGoDelimiter: boolean; allowDollarDollarString: boolean; noSplit: boolean; + doubleDashComments: boolean; + multilineComments: boolean; + javaScriptComments: boolean; } export const defaultSplitterOptions: SplitterOptions = { @@ -20,6 +23,10 @@ export const defaultSplitterOptions: SplitterOptions = { allowGoDelimiter: false, allowDollarDollarString: false, noSplit: false, + + doubleDashComments: true, + multilineComments: true, + javaScriptComments: false, }; export const mysqlSplitterOptions: SplitterOptions = { @@ -59,6 +66,14 @@ export const sqliteSplitterOptions: SplitterOptions = { stringEscapes: { "'": "'", '"': '"' }, }; +export const mongoSplitterOptions: SplitterOptions = { + ...defaultSplitterOptions, + + stringsBegins: ["'", '"'], + stringsEnds: { "'": "'", '"': '"' }, + stringEscapes: { "'": '\\', '"': '\\' }, +}; + export const noSplitSplitterOptions: SplitterOptions = { ...defaultSplitterOptions, diff --git a/packages/query-splitter/src/splitQuery.ts b/packages/query-splitter/src/splitQuery.ts index 20dc08764..3f6f423f8 100644 --- a/packages/query-splitter/src/splitQuery.ts +++ b/packages/query-splitter/src/splitQuery.ts @@ -113,7 +113,7 @@ function scanToken(context: SplitLineContext): Token { return EOLN_TOKEN; } - if (ch == '-' && s[pos + 1] == '-') { + if (context.options.doubleDashComments && ch == '-' && s[pos + 1] == '-') { while (pos < context.end && s[pos] != '\n') pos++; return { type: 'comment', @@ -121,7 +121,7 @@ function scanToken(context: SplitLineContext): Token { }; } - if (ch == '/' && s[pos + 1] == '*') { + if (context.options.multilineComments && ch == '/' && s[pos + 1] == '*') { pos += 2; while (pos < context.end) { if (s[pos] == '*' && s[pos + 1] == '/') break; @@ -222,7 +222,7 @@ export function splitQueryLine(context: SplitLineContext) { } export function getInitialDelimiter(options: SplitterOptions) { - return options?.allowSemicolon === false ? null : SEMICOLON + return options?.allowSemicolon === false ? null : SEMICOLON; } export function splitQuery(sql: string, options: SplitterOptions = null): string[] { const usedOptions = { diff --git a/packages/query-splitter/src/splitter.test.ts b/packages/query-splitter/src/splitter.test.ts index f2b2b237b..bc82b2088 100644 --- a/packages/query-splitter/src/splitter.test.ts +++ b/packages/query-splitter/src/splitter.test.ts @@ -1,4 +1,10 @@ -import { mysqlSplitterOptions, mssqlSplitterOptions, postgreSplitterOptions, noSplitSplitterOptions } from './options'; +import { + mysqlSplitterOptions, + mssqlSplitterOptions, + postgreSplitterOptions, + mongoSplitterOptions, + noSplitSplitterOptions, +} from './options'; import { splitQuery } from './splitQuery'; test('simple query', () => { @@ -77,3 +83,9 @@ test('no split', () => { const output = splitQuery(input, noSplitSplitterOptions); expect(output).toEqual(['SELECT 1;SELECT 2']); }); + +test('split mongo', () => { + const input = 'db.collection.insert({x:1});db.collection.insert({y:2})'; + const output = splitQuery(input, mongoSplitterOptions); + expect(output).toEqual(['db.collection.insert({x:1})', 'db.collection.insert({y:2})']); +}); diff --git a/packages/web/src/datagrid/DataGridCore.svelte b/packages/web/src/datagrid/DataGridCore.svelte index 1c6a42a7c..890156e7a 100644 --- a/packages/web/src/datagrid/DataGridCore.svelte +++ b/packages/web/src/datagrid/DataGridCore.svelte @@ -250,6 +250,7 @@ import { showModal } from '../modals/modalTools'; import { updateStatuBarInfo } from '../widgets/StatusBar.svelte'; import StatusBarTabItem from '../widgets/StatusBarTabItem.svelte'; + import { findCommand } from '../commands/runCommand'; export let onLoadNextData = undefined; export let grider = undefined; @@ -265,6 +266,8 @@ export let focusOnVisible = false; export let formViewAvailable = false; export let errorMessage = undefined; + export let pureName = undefined; + export let schemaName = undefined; export let isLoadedAll; export let loadedTime; @@ -379,8 +382,8 @@ // @ts-ignore const columns = colIndexes.map(col => realColumnUniqueNames[col]); copyRowsToClipboard(format, columns, rows, { - schemaName: display?.baseTable?.schemaName, - pureName: display?.baseTable?.pureName || 'target', + schemaName, + pureName: pureName || 'target', driver: display?.driver || driverBase, keyColumns: display?.baseTable?.primaryKey?.columns?.map(col => col.columnName) || [ display?.columns ? display?.columns[0].columnName : columns[0], @@ -1218,6 +1221,12 @@ {#if display.filterCount > 0} display.clearFilters()} /> {/if} + { + findCommand('collectionTable.newJson')?.onClick(); + }} + /> {:else if grider.errors && grider.errors.length > 0}
diff --git a/packages/web/src/modals/EditJsonModal.svelte b/packages/web/src/modals/EditJsonModal.svelte index ea17456ec..345596401 100644 --- a/packages/web/src/modals/EditJsonModal.svelte +++ b/packages/web/src/modals/EditJsonModal.svelte @@ -29,7 +29,7 @@
- { try { diff --git a/packages/web/src/tabs/CollectionDataTab.svelte b/packages/web/src/tabs/CollectionDataTab.svelte index e49af5e63..73dd2da66 100644 --- a/packages/web/src/tabs/CollectionDataTab.svelte +++ b/packages/web/src/tabs/CollectionDataTab.svelte @@ -55,6 +55,7 @@ import { registerMenu } from '../utility/contextMenu'; import EditJsonModal from '../modals/EditJsonModal.svelte'; import ChangeSetGrider from '../datagrid/ChangeSetGrider'; + import { setContext } from 'svelte'; export let tabid; export let conid; @@ -89,7 +90,8 @@ config.update, $cache, cache.update, - loadedRows + loadedRows, + $changeSetStore?.value ) : null; // $: console.log('LOADED ROWS MONGO', loadedRows); @@ -145,6 +147,9 @@ } registerMenu({ command: 'collectionTable.save', tag: 'save' }, { command: 'collectionTable.newJson', tag: 'edit' }); + + const collapsedLeftColumnStore = writable(false); + setContext('collapsedLeftColumnStore', collapsedLeftColumnStore); (columns, rows, options) => { return dmp.s; }; +const clipboardMongoInsertFormatter = () => (columns, rows, options) => { + const { pureName } = options; + return rows.map(row => `db.${pureName}.insert(${JSON.stringify(_.pick(row, columns), undefined, 2)});`).join('\n'); +}; + export function formatClipboardRows(format, columns, rows, options) { if (format in copyRowsFormatDefs) { return copyRowsFormatDefs[format].formatter(columns, rows, options); @@ -185,4 +190,9 @@ export const copyRowsFormatDefs = { name: 'SQL UPDATEs', formatter: clipboardUpdatesFormatter(), }, + mongoInsert: { + label: 'Copy as Mongo INSERTs', + name: 'Mongo UPDATEs', + formatter: clipboardMongoInsertFormatter(), + }, }; diff --git a/plugins/dbgate-plugin-mongo/src/frontend/driver.js b/plugins/dbgate-plugin-mongo/src/frontend/driver.js index 5eed31e57..431574953 100644 --- a/plugins/dbgate-plugin-mongo/src/frontend/driver.js +++ b/plugins/dbgate-plugin-mongo/src/frontend/driver.js @@ -1,7 +1,7 @@ const _isString = require('lodash/isString'); const { driverBase } = global.DBGATE_TOOLS; const Dumper = require('./Dumper'); -const { noSplitSplitterOptions } = require('dbgate-query-splitter/lib/options'); +const { mongoSplitterOptions } = require('dbgate-query-splitter/lib/options'); const mongoIdRegex = /^[0-9a-f]{24}$/; @@ -36,7 +36,7 @@ const driver = { supportsDatabaseUrl: true, databaseUrlPlaceholder: 'e.g. mongodb://username:password@mongodb.mydomain.net/dbname', - getQuerySplitterOptions: () => noSplitSplitterOptions, + getQuerySplitterOptions: () => mongoSplitterOptions, showConnectionField: (field, values) => { if (field == 'useDatabaseUrl') return true;