mongo query splitter, copy as mongo insert

This commit is contained in:
Jan Prochazka
2021-12-02 10:00:48 +01:00
parent 368993597c
commit 536897a84c
10 changed files with 67 additions and 14 deletions

View File

@@ -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,

View File

@@ -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;

View File

@@ -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,

View File

@@ -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 = {

View File

@@ -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})']);
});

View File

@@ -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}
<FormStyledButton value="Reset filter" on:click={() => display.clearFilters()} />
{/if}
<FormStyledButton
value="Add document"
on:click={() => {
findCommand('collectionTable.newJson')?.onClick();
}}
/>
</div>
{:else if grider.errors && grider.errors.length > 0}
<div>

View File

@@ -29,7 +29,7 @@
</div>
<div slot="footer">
<FormSubmit
<FormStyledButton
value="Save"
on:click={() => {
try {

View File

@@ -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);
</script>
<DataGrid

View File

@@ -132,6 +132,11 @@ const clipboardUpdatesFormatter = () => (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(),
},
};

View File

@@ -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;