correct export from read-only connection

This commit is contained in:
Jan Prochazka
2022-03-20 09:47:39 +01:00
parent 1a81952ce7
commit 6fb582249c
9 changed files with 85 additions and 20 deletions

View File

@@ -1,14 +1,26 @@
const requireEngineDriver = require('../utility/requireEngineDriver'); const requireEngineDriver = require('../utility/requireEngineDriver');
const { decryptConnection } = require('../utility/crypting');
const connectUtility = require('../utility/connectUtility'); const connectUtility = require('../utility/connectUtility');
async function queryReader({ connection, sql }) { async function queryReader({
console.log(`Reading query ${sql}`); connection,
query,
queryType,
// obsolete; use query instead
sql,
}) {
// if (sql && json) {
// throw new Error('Only one of sql or json could be set');
// }
// if (!sql && !json) {
// throw new Error('One of sql or json must be set');
// }
console.log(`Reading query ${query || sql}`);
// else console.log(`Reading query ${JSON.stringify(json)}`);
const driver = requireEngineDriver(connection); const driver = requireEngineDriver(connection);
const pool = await connectUtility(driver, connection, 'script'); const pool = await connectUtility(driver, connection, queryType == 'json' ? 'read' : 'script');
console.log(`Connected.`); console.log(`Connected.`);
return await driver.readQuery(pool, sql); return queryType == 'json' ? await driver.readJsonQuery(pool, query) : await driver.readQuery(pool, query || sql);
} }
module.exports = queryReader; module.exports = queryReader;

View File

@@ -574,6 +574,13 @@ export abstract class GridDisplay {
return sql; return sql;
} }
getExportQueryJson(postprocessSelect = null) {
const select = this.createSelect({ isExport: true });
if (!select) return null;
if (postprocessSelect) postprocessSelect(select);
return select;
}
getExportColumnMap() { getExportColumnMap() {
const changesDefined = this.config.hiddenColumns?.length > 0 || this.config.addedColumns?.length > 0; const changesDefined = this.config.hiddenColumns?.length > 0 || this.config.addedColumns?.length > 0;
if (this.isDynamicStructure && !changesDefined) { if (this.isDynamicStructure && !changesDefined) {

View File

@@ -1,4 +1,4 @@
import _compact from 'lodash/compact' import _compact from 'lodash/compact';
import { SqlDumper } from './SqlDumper'; import { SqlDumper } from './SqlDumper';
import { splitQuery } from 'dbgate-query-splitter'; import { splitQuery } from 'dbgate-query-splitter';
import { dumpSqlSelect } from 'dbgate-sqltree'; import { dumpSqlSelect } from 'dbgate-sqltree';
@@ -105,4 +105,9 @@ export const driverBase = {
const resp = await this.query(pool, dmp.s); const resp = await this.query(pool, dmp.s);
return resp.rows; return resp.rows;
}, },
readJsonQuery(pool, select, structure) {
const dmp = this.createDumper();
dumpSqlSelect(dmp, select);
return this.readQuery(pool, dmp.s, structure);
},
}; };

View File

@@ -47,7 +47,7 @@ export interface EngineDriver {
title: string; title: string;
defaultPort?: number; defaultPort?: number;
databaseEngineTypes: string[]; databaseEngineTypes: string[];
readOnlySessions: boolean, readOnlySessions: boolean;
supportedKeyTypes: { name: string; label: string }[]; supportedKeyTypes: { name: string; label: string }[];
supportsDatabaseUrl?: boolean; supportsDatabaseUrl?: boolean;
isElectronOnly?: boolean; isElectronOnly?: boolean;
@@ -62,6 +62,7 @@ export interface EngineDriver {
query(pool: any, sql: string, options?: QueryOptions): Promise<QueryResult>; query(pool: any, sql: string, options?: QueryOptions): Promise<QueryResult>;
stream(pool: any, sql: string, options: StreamOptions); stream(pool: any, sql: string, options: StreamOptions);
readQuery(pool: any, sql: string, structure?: TableInfo): Promise<stream.Readable>; readQuery(pool: any, sql: string, structure?: TableInfo): Promise<stream.Readable>;
readJsonQuery(pool: any, query: any, structure?: TableInfo): Promise<stream.Readable>;
writeTable(pool: any, name: NamedObjectInfo, options: WriteTableOptions): Promise<stream.Writeable>; writeTable(pool: any, name: NamedObjectInfo, options: WriteTableOptions): Promise<stream.Writeable>;
analyseSingleObject( analyseSingleObject(
pool: any, pool: any,

View File

@@ -168,12 +168,24 @@
.sort(${JSON.stringify(buildMongoSort($$props) || {})})`; .sort(${JSON.stringify(buildMongoSort($$props) || {})})`;
} }
export function exportGrid() { function getExportQueryJson() {
return {
collection: pureName,
condition: buildGridMongoCondition($$props) || {},
sort: buildMongoSort($$props) || {},
};
}
export async function exportGrid() {
const coninfo = await getConnectionInfo({ conid });
const initialValues: any = {}; const initialValues: any = {};
initialValues.sourceStorageType = 'query'; initialValues.sourceStorageType = 'query';
initialValues.sourceConnectionId = conid; initialValues.sourceConnectionId = conid;
initialValues.sourceDatabaseName = database; initialValues.sourceDatabaseName = database;
initialValues.sourceSql = getExportQuery(); initialValues.sourceQuery = coninfo.isReadOnly
? JSON.stringify(getExportQueryJson(), undefined, 2)
: getExportQuery();
initialValues.sourceQueryType = coninfo.isReadOnly ? 'json' : 'native';
initialValues.sourceList = [pureName]; initialValues.sourceList = [pureName];
initialValues[`columns_${pureName}`] = display.getExportColumnMap(); initialValues[`columns_${pureName}`] = display.getExportColumnMap();
showModal(ImportExportModal, { initialValues }); showModal(ImportExportModal, { initialValues });
@@ -204,7 +216,8 @@
functionName: 'queryReader', functionName: 'queryReader',
props: { props: {
connection: extractShellConnection(coninfo, database), connection: extractShellConnection(coninfo, database),
sql: getExportQuery(), queryType: coninfo.isReadOnly ? 'json' : 'native',
query: coninfo.isReadOnly ? getExportQueryJson() : getExportQuery(),
}, },
}, },
fmt, fmt,

View File

@@ -129,12 +129,17 @@
// $: console.log('GRIDER', grider); // $: console.log('GRIDER', grider);
// $: if (onChangeGrider) onChangeGrider(grider); // $: if (onChangeGrider) onChangeGrider(grider);
export function exportGrid() { export async function exportGrid() {
const coninfo = await getConnectionInfo({ conid });
const initialValues: any = {}; const initialValues: any = {};
initialValues.sourceStorageType = 'query'; initialValues.sourceStorageType = 'query';
initialValues.sourceConnectionId = conid; initialValues.sourceConnectionId = conid;
initialValues.sourceDatabaseName = database; initialValues.sourceDatabaseName = database;
initialValues.sourceSql = display.getExportQuery(); initialValues.sourceQuery = coninfo.isReadOnly
? JSON.stringify(display.getExportQueryJson(), undefined, 2)
: display.getExportQuery();
initialValues.sourceQueryType = coninfo.isReadOnly ? 'json' : 'native';
initialValues.sourceList = display.baseTableOrSimilar ? [display.baseTableOrSimilar.pureName] : []; initialValues.sourceList = display.baseTableOrSimilar ? [display.baseTableOrSimilar.pureName] : [];
initialValues[`columns_${pureName}`] = display.getExportColumnMap(); initialValues[`columns_${pureName}`] = display.getExportColumnMap();
showModal(ImportExportModal, { initialValues }); showModal(ImportExportModal, { initialValues });
@@ -189,7 +194,8 @@
functionName: 'queryReader', functionName: 'queryReader',
props: { props: {
connection: extractShellConnection(coninfo, database), connection: extractShellConnection(coninfo, database),
sql: display.getExportQuery(), queryType: coninfo.isReadOnly ? 'json' : 'native',
query: coninfo.isReadOnly ? display.getExportQueryJson() : display.getExportQuery(),
}, },
}, },
fmt, fmt,

View File

@@ -21,6 +21,7 @@
import FormSchemaSelect from './FormSchemaSelect.svelte'; import FormSchemaSelect from './FormSchemaSelect.svelte';
import FormTablesSelect from './FormTablesSelect.svelte'; import FormTablesSelect from './FormTablesSelect.svelte';
import { findEngineDriver } from 'dbgate-tools'; import { findEngineDriver } from 'dbgate-tools';
import AceEditor from '../query/AceEditor.svelte';
export let direction; export let direction;
export let storageTypeField; export let storageTypeField;
@@ -137,12 +138,19 @@
{#if storageType == 'query'} {#if storageType == 'query'}
<div class="label">Query</div> <div class="label">Query</div>
<div class="sqlwrap"> <div class="sqlwrap">
<SqlEditor {#if $values.sourceQueryType == 'json'}
value={$values.sourceSql} <AceEditor
on:input={e => setFieldValue('sourceSql', e.detail)} value={$values.sourceQuery}
{engine} on:input={e => setFieldValue('sourceQuery', e.detail)}
focusOnCreate mode="json"
/> />
{:else}
<SqlEditor
value={$values.sourceQuery}
on:input={e => setFieldValue('sourceQuery', e.detail)}
{engine}
/>
{/if}
</div> </div>
{/if} {/if}

View File

@@ -78,7 +78,8 @@ function getSourceExpr(extensions, sourceName, values, sourceConnection, sourceD
{ {
connection: sourceConnection, connection: sourceConnection,
...extractDriverApiParameters(values, 'source', sourceDriver), ...extractDriverApiParameters(values, 'source', sourceDriver),
sql: values.sourceSql, queryType: values.sourceQueryType,
query: values.sourceQueryType == 'json' ? JSON.parse(values.sourceQuery) : values.sourceQuery,
}, },
]; ];
} }

View File

@@ -325,6 +325,18 @@ const driver = {
return { errorMessage: err.message }; return { errorMessage: err.message };
} }
}, },
readJsonQuery(pool, select, structure) {
const { collection, condition, sort } = select;
const db = pool.__getDatabase();
const res = db
.collection(collection)
.find(condition || {})
.sort(sort || {});
return res;
},
}; };
module.exports = driver; module.exports = driver;