mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-27 09:06:00 +00:00
mongo query splitter, copy as mongo insert
This commit is contained in:
@@ -228,7 +228,7 @@ function changeSetInsertToSql(
|
|||||||
const table = dbinfo.tables.find(x => x.schemaName == item.schemaName && x.pureName == item.pureName);
|
const table = dbinfo.tables.find(x => x.schemaName == item.schemaName && x.pureName == item.pureName);
|
||||||
if (table) {
|
if (table) {
|
||||||
const autoIncCol = table.columns.find(x => x.autoIncrement);
|
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)) {
|
if (autoIncCol && fields.find(x => x.targetColumn == autoIncCol.columnName)) {
|
||||||
autoInc = true;
|
autoInc = true;
|
||||||
}
|
}
|
||||||
@@ -375,7 +375,7 @@ export function getChangeSetInsertedRows(changeSet: ChangeSet, name?: NamedObjec
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function changeSetInsertNewRow(changeSet: ChangeSet, name?: NamedObjectInfo): ChangeSet {
|
export function changeSetInsertNewRow(changeSet: ChangeSet, name?: NamedObjectInfo): ChangeSet {
|
||||||
console.log('INSERT', name);
|
// console.log('INSERT', name);
|
||||||
const insertedRows = getChangeSetInsertedRows(changeSet, name);
|
const insertedRows = getChangeSetInsertedRows(changeSet, name);
|
||||||
return {
|
return {
|
||||||
...changeSet,
|
...changeSet,
|
||||||
|
|||||||
@@ -89,10 +89,12 @@ export class CollectionGridDisplay extends GridDisplay {
|
|||||||
setConfig: ChangeConfigFunc,
|
setConfig: ChangeConfigFunc,
|
||||||
cache: GridCache,
|
cache: GridCache,
|
||||||
setCache: ChangeCacheFunc,
|
setCache: ChangeCacheFunc,
|
||||||
loadedRows
|
loadedRows,
|
||||||
|
changeSet
|
||||||
) {
|
) {
|
||||||
super(config, setConfig, cache, setCache, driver);
|
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.filterable = true;
|
||||||
this.sortable = true;
|
this.sortable = true;
|
||||||
this.editable = true;
|
this.editable = true;
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ export interface SplitterOptions {
|
|||||||
allowGoDelimiter: boolean;
|
allowGoDelimiter: boolean;
|
||||||
allowDollarDollarString: boolean;
|
allowDollarDollarString: boolean;
|
||||||
noSplit: boolean;
|
noSplit: boolean;
|
||||||
|
doubleDashComments: boolean;
|
||||||
|
multilineComments: boolean;
|
||||||
|
javaScriptComments: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultSplitterOptions: SplitterOptions = {
|
export const defaultSplitterOptions: SplitterOptions = {
|
||||||
@@ -20,6 +23,10 @@ export const defaultSplitterOptions: SplitterOptions = {
|
|||||||
allowGoDelimiter: false,
|
allowGoDelimiter: false,
|
||||||
allowDollarDollarString: false,
|
allowDollarDollarString: false,
|
||||||
noSplit: false,
|
noSplit: false,
|
||||||
|
|
||||||
|
doubleDashComments: true,
|
||||||
|
multilineComments: true,
|
||||||
|
javaScriptComments: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const mysqlSplitterOptions: SplitterOptions = {
|
export const mysqlSplitterOptions: SplitterOptions = {
|
||||||
@@ -59,6 +66,14 @@ export const sqliteSplitterOptions: SplitterOptions = {
|
|||||||
stringEscapes: { "'": "'", '"': '"' },
|
stringEscapes: { "'": "'", '"': '"' },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const mongoSplitterOptions: SplitterOptions = {
|
||||||
|
...defaultSplitterOptions,
|
||||||
|
|
||||||
|
stringsBegins: ["'", '"'],
|
||||||
|
stringsEnds: { "'": "'", '"': '"' },
|
||||||
|
stringEscapes: { "'": '\\', '"': '\\' },
|
||||||
|
};
|
||||||
|
|
||||||
export const noSplitSplitterOptions: SplitterOptions = {
|
export const noSplitSplitterOptions: SplitterOptions = {
|
||||||
...defaultSplitterOptions,
|
...defaultSplitterOptions,
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ function scanToken(context: SplitLineContext): Token {
|
|||||||
return EOLN_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++;
|
while (pos < context.end && s[pos] != '\n') pos++;
|
||||||
return {
|
return {
|
||||||
type: 'comment',
|
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;
|
pos += 2;
|
||||||
while (pos < context.end) {
|
while (pos < context.end) {
|
||||||
if (s[pos] == '*' && s[pos + 1] == '/') break;
|
if (s[pos] == '*' && s[pos + 1] == '/') break;
|
||||||
@@ -222,7 +222,7 @@ export function splitQueryLine(context: SplitLineContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getInitialDelimiter(options: SplitterOptions) {
|
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[] {
|
export function splitQuery(sql: string, options: SplitterOptions = null): string[] {
|
||||||
const usedOptions = {
|
const usedOptions = {
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
import { mysqlSplitterOptions, mssqlSplitterOptions, postgreSplitterOptions, noSplitSplitterOptions } from './options';
|
import {
|
||||||
|
mysqlSplitterOptions,
|
||||||
|
mssqlSplitterOptions,
|
||||||
|
postgreSplitterOptions,
|
||||||
|
mongoSplitterOptions,
|
||||||
|
noSplitSplitterOptions,
|
||||||
|
} from './options';
|
||||||
import { splitQuery } from './splitQuery';
|
import { splitQuery } from './splitQuery';
|
||||||
|
|
||||||
test('simple query', () => {
|
test('simple query', () => {
|
||||||
@@ -77,3 +83,9 @@ test('no split', () => {
|
|||||||
const output = splitQuery(input, noSplitSplitterOptions);
|
const output = splitQuery(input, noSplitSplitterOptions);
|
||||||
expect(output).toEqual(['SELECT 1;SELECT 2']);
|
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})']);
|
||||||
|
});
|
||||||
|
|||||||
@@ -250,6 +250,7 @@
|
|||||||
import { showModal } from '../modals/modalTools';
|
import { showModal } from '../modals/modalTools';
|
||||||
import { updateStatuBarInfo } from '../widgets/StatusBar.svelte';
|
import { updateStatuBarInfo } from '../widgets/StatusBar.svelte';
|
||||||
import StatusBarTabItem from '../widgets/StatusBarTabItem.svelte';
|
import StatusBarTabItem from '../widgets/StatusBarTabItem.svelte';
|
||||||
|
import { findCommand } from '../commands/runCommand';
|
||||||
|
|
||||||
export let onLoadNextData = undefined;
|
export let onLoadNextData = undefined;
|
||||||
export let grider = undefined;
|
export let grider = undefined;
|
||||||
@@ -265,6 +266,8 @@
|
|||||||
export let focusOnVisible = false;
|
export let focusOnVisible = false;
|
||||||
export let formViewAvailable = false;
|
export let formViewAvailable = false;
|
||||||
export let errorMessage = undefined;
|
export let errorMessage = undefined;
|
||||||
|
export let pureName = undefined;
|
||||||
|
export let schemaName = undefined;
|
||||||
|
|
||||||
export let isLoadedAll;
|
export let isLoadedAll;
|
||||||
export let loadedTime;
|
export let loadedTime;
|
||||||
@@ -379,8 +382,8 @@
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const columns = colIndexes.map(col => realColumnUniqueNames[col]);
|
const columns = colIndexes.map(col => realColumnUniqueNames[col]);
|
||||||
copyRowsToClipboard(format, columns, rows, {
|
copyRowsToClipboard(format, columns, rows, {
|
||||||
schemaName: display?.baseTable?.schemaName,
|
schemaName,
|
||||||
pureName: display?.baseTable?.pureName || 'target',
|
pureName: pureName || 'target',
|
||||||
driver: display?.driver || driverBase,
|
driver: display?.driver || driverBase,
|
||||||
keyColumns: display?.baseTable?.primaryKey?.columns?.map(col => col.columnName) || [
|
keyColumns: display?.baseTable?.primaryKey?.columns?.map(col => col.columnName) || [
|
||||||
display?.columns ? display?.columns[0].columnName : columns[0],
|
display?.columns ? display?.columns[0].columnName : columns[0],
|
||||||
@@ -1218,6 +1221,12 @@
|
|||||||
{#if display.filterCount > 0}
|
{#if display.filterCount > 0}
|
||||||
<FormStyledButton value="Reset filter" on:click={() => display.clearFilters()} />
|
<FormStyledButton value="Reset filter" on:click={() => display.clearFilters()} />
|
||||||
{/if}
|
{/if}
|
||||||
|
<FormStyledButton
|
||||||
|
value="Add document"
|
||||||
|
on:click={() => {
|
||||||
|
findCommand('collectionTable.newJson')?.onClick();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{:else if grider.errors && grider.errors.length > 0}
|
{:else if grider.errors && grider.errors.length > 0}
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div slot="footer">
|
<div slot="footer">
|
||||||
<FormSubmit
|
<FormStyledButton
|
||||||
value="Save"
|
value="Save"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
import { registerMenu } from '../utility/contextMenu';
|
import { registerMenu } from '../utility/contextMenu';
|
||||||
import EditJsonModal from '../modals/EditJsonModal.svelte';
|
import EditJsonModal from '../modals/EditJsonModal.svelte';
|
||||||
import ChangeSetGrider from '../datagrid/ChangeSetGrider';
|
import ChangeSetGrider from '../datagrid/ChangeSetGrider';
|
||||||
|
import { setContext } from 'svelte';
|
||||||
|
|
||||||
export let tabid;
|
export let tabid;
|
||||||
export let conid;
|
export let conid;
|
||||||
@@ -89,7 +90,8 @@
|
|||||||
config.update,
|
config.update,
|
||||||
$cache,
|
$cache,
|
||||||
cache.update,
|
cache.update,
|
||||||
loadedRows
|
loadedRows,
|
||||||
|
$changeSetStore?.value
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
// $: console.log('LOADED ROWS MONGO', loadedRows);
|
// $: console.log('LOADED ROWS MONGO', loadedRows);
|
||||||
@@ -145,6 +147,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
registerMenu({ command: 'collectionTable.save', tag: 'save' }, { command: 'collectionTable.newJson', tag: 'edit' });
|
registerMenu({ command: 'collectionTable.save', tag: 'save' }, { command: 'collectionTable.newJson', tag: 'edit' });
|
||||||
|
|
||||||
|
const collapsedLeftColumnStore = writable(false);
|
||||||
|
setContext('collapsedLeftColumnStore', collapsedLeftColumnStore);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<DataGrid
|
<DataGrid
|
||||||
|
|||||||
@@ -132,6 +132,11 @@ const clipboardUpdatesFormatter = () => (columns, rows, options) => {
|
|||||||
return dmp.s;
|
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) {
|
export function formatClipboardRows(format, columns, rows, options) {
|
||||||
if (format in copyRowsFormatDefs) {
|
if (format in copyRowsFormatDefs) {
|
||||||
return copyRowsFormatDefs[format].formatter(columns, rows, options);
|
return copyRowsFormatDefs[format].formatter(columns, rows, options);
|
||||||
@@ -185,4 +190,9 @@ export const copyRowsFormatDefs = {
|
|||||||
name: 'SQL UPDATEs',
|
name: 'SQL UPDATEs',
|
||||||
formatter: clipboardUpdatesFormatter(),
|
formatter: clipboardUpdatesFormatter(),
|
||||||
},
|
},
|
||||||
|
mongoInsert: {
|
||||||
|
label: 'Copy as Mongo INSERTs',
|
||||||
|
name: 'Mongo UPDATEs',
|
||||||
|
formatter: clipboardMongoInsertFormatter(),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const _isString = require('lodash/isString');
|
const _isString = require('lodash/isString');
|
||||||
const { driverBase } = global.DBGATE_TOOLS;
|
const { driverBase } = global.DBGATE_TOOLS;
|
||||||
const Dumper = require('./Dumper');
|
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}$/;
|
const mongoIdRegex = /^[0-9a-f]{24}$/;
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ const driver = {
|
|||||||
supportsDatabaseUrl: true,
|
supportsDatabaseUrl: true,
|
||||||
databaseUrlPlaceholder: 'e.g. mongodb://username:password@mongodb.mydomain.net/dbname',
|
databaseUrlPlaceholder: 'e.g. mongodb://username:password@mongodb.mydomain.net/dbname',
|
||||||
|
|
||||||
getQuerySplitterOptions: () => noSplitSplitterOptions,
|
getQuerySplitterOptions: () => mongoSplitterOptions,
|
||||||
|
|
||||||
showConnectionField: (field, values) => {
|
showConnectionField: (field, values) => {
|
||||||
if (field == 'useDatabaseUrl') return true;
|
if (field == 'useDatabaseUrl') return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user