query history - prepare

This commit is contained in:
Jan Prochazka
2021-06-03 14:26:21 +02:00
parent bebdf3f43b
commit 2a47f60987
26 changed files with 131 additions and 51 deletions

View File

@@ -33,6 +33,7 @@
"express-basic-auth": "^1.2.0", "express-basic-auth": "^1.2.0",
"express-fileupload": "^1.2.0", "express-fileupload": "^1.2.0",
"fs-extra": "^9.1.0", "fs-extra": "^9.1.0",
"fs-reverse": "^0.0.3",
"get-port": "^5.1.1", "get-port": "^5.1.1",
"http": "^0.0.0", "http": "^0.0.0",
"json-stable-stringify": "^1.0.1", "json-stable-stringify": "^1.0.1",
@@ -71,4 +72,4 @@
"optionalDependencies": { "optionalDependencies": {
"msnodesqlv8": "^2.0.10" "msnodesqlv8": "^2.0.10"
} }
} }

View File

@@ -0,0 +1,45 @@
const fsReverse = require('fs-reverse');
const fs = require('fs-extra');
const path = require('path');
const { datadir } = require('../utility/directories');
const _ = require('lodash');
const { filterName } = require('dbgate-tools');
function readCore(reader, skip, limit, filter) {
return new Promise(resolve => {
const res = [];
let readed = 0;
reader.on('data', line => {
const json = JSON.parse(line);
if (filterName(filter, json.sql)) {
if (!skip || readed >= skip) {
res.push(json);
}
readed++;
if (limit && readed > (skip || 0) + limit) {
reader.destroy();
resolve(res);
}
}
});
reader.on('end', () => resolve(res));
});
}
module.exports = {
read_meta: 'get',
async read({ skip, limit, filter }) {
const fileName = path.join(datadir(), 'query-history.jsonl');
// @ts-ignore
if (!(await fs.exists(fileName))) return [];
const reader = fsReverse(fileName);
const res = await readCore(reader, skip, limit, filter);
return res;
},
write_meta: 'post',
async write({ data }) {
const fileName = path.join(datadir(), 'query-history.jsonl');
await fs.appendFile(fileName, JSON.stringify(data) + '\n');
},
};

View File

@@ -27,6 +27,7 @@ const uploads = require('./controllers/uploads');
const plugins = require('./controllers/plugins'); const plugins = require('./controllers/plugins');
const files = require('./controllers/files'); const files = require('./controllers/files');
const scheduler = require('./controllers/scheduler'); const scheduler = require('./controllers/scheduler');
const queryHistory = require('./controllers/queryHistory');
const { rundir } = require('./utility/directories'); const { rundir } = require('./utility/directories');
const platformInfo = require('./utility/platformInfo'); const platformInfo = require('./utility/platformInfo');
@@ -102,6 +103,7 @@ function start() {
useController(app, '/plugins', plugins); useController(app, '/plugins', plugins);
useController(app, '/files', files); useController(app, '/files', files);
useController(app, '/scheduler', scheduler); useController(app, '/scheduler', scheduler);
useController(app, '/query-history', queryHistory);
// if (process.env.PAGES_DIRECTORY) { // if (process.env.PAGES_DIRECTORY) {
// app.use('/pages', express.static(process.env.PAGES_DIRECTORY)); // app.use('/pages', express.static(process.env.PAGES_DIRECTORY));

View File

@@ -1,19 +1,7 @@
import _ from 'lodash'; import _ from 'lodash';
import { GridConfig, GridCache, GridConfigColumns, createGridCache, GroupFunc } from './GridConfig'; import { GridConfig, GridCache, GridConfigColumns, createGridCache, GroupFunc } from './GridConfig';
import { import { TableInfo, EngineDriver, DatabaseInfo, SqlDialect } from 'dbgate-types';
ForeignKeyInfo, import { getFilterValueExpression } from 'dbgate-filterparser';
TableInfo,
ColumnInfo,
EngineDriver,
NamedObjectInfo,
DatabaseInfo,
SqlDialect,
} from 'dbgate-types';
import { parseFilter, getFilterType, getFilterValueExpression } from 'dbgate-filterparser';
import { filterName } from './filterName';
import { ChangeSetFieldDefinition, ChangeSetRowDefinition } from './ChangeSet';
import { Expression, Select, treeToSql, dumpSqlSelect, Condition } from 'dbgate-sqltree';
import { isTypeLogical } from 'dbgate-tools';
import { ChangeCacheFunc, ChangeConfigFunc, DisplayColumn } from './GridDisplay'; import { ChangeCacheFunc, ChangeConfigFunc, DisplayColumn } from './GridDisplay';
export class FormViewDisplay { export class FormViewDisplay {

View File

@@ -11,7 +11,7 @@ import {
SqlDialect, SqlDialect,
} from 'dbgate-types'; } from 'dbgate-types';
import { parseFilter, getFilterType } from 'dbgate-filterparser'; import { parseFilter, getFilterType } from 'dbgate-filterparser';
import { filterName } from './filterName'; import { filterName } from 'dbgate-tools';
import { ChangeSetFieldDefinition, ChangeSetRowDefinition } from './ChangeSet'; import { ChangeSetFieldDefinition, ChangeSetRowDefinition } from './ChangeSet';
import { Expression, Select, treeToSql, dumpSqlSelect, Condition } from 'dbgate-sqltree'; import { Expression, Select, treeToSql, dumpSqlSelect, Condition } from 'dbgate-sqltree';
import { isTypeLogical } from 'dbgate-tools'; import { isTypeLogical } from 'dbgate-tools';

View File

@@ -12,7 +12,6 @@ import {
Condition, Condition,
OrderByExpression, OrderByExpression,
} from 'dbgate-sqltree'; } from 'dbgate-sqltree';
import { filterName } from './filterName';
import { TableGridDisplay } from './TableGridDisplay'; import { TableGridDisplay } from './TableGridDisplay';
import stableStringify from 'json-stable-stringify'; import stableStringify from 'json-stable-stringify';
import { ChangeSetFieldDefinition, ChangeSetRowDefinition } from './ChangeSet'; import { ChangeSetFieldDefinition, ChangeSetRowDefinition } from './ChangeSet';

View File

@@ -1,9 +1,9 @@
import _ from 'lodash'; import _ from 'lodash';
import { filterName } from 'dbgate-tools';
import { GridDisplay, ChangeCacheFunc, DisplayColumn, DisplayedColumnInfo, ChangeConfigFunc } from './GridDisplay'; import { GridDisplay, ChangeCacheFunc, DisplayColumn, DisplayedColumnInfo, ChangeConfigFunc } from './GridDisplay';
import { TableInfo, EngineDriver, ViewInfo, ColumnInfo, NamedObjectInfo, DatabaseInfo } from 'dbgate-types'; import { TableInfo, EngineDriver, ViewInfo, ColumnInfo, NamedObjectInfo, DatabaseInfo } from 'dbgate-types';
import { GridConfig, GridCache, createGridCache } from './GridConfig'; import { GridConfig, GridCache, createGridCache } from './GridConfig';
import { Expression, Select, treeToSql, dumpSqlSelect } from 'dbgate-sqltree'; import { Expression, Select, treeToSql, dumpSqlSelect } from 'dbgate-sqltree';
import { filterName } from './filterName';
export class TableGridDisplay extends GridDisplay { export class TableGridDisplay extends GridDisplay {
public table: TableInfo; public table: TableInfo;

View File

@@ -4,7 +4,6 @@ export * from './TableGridDisplay';
export * from './ViewGridDisplay'; export * from './ViewGridDisplay';
export * from './JslGridDisplay'; export * from './JslGridDisplay';
export * from './ChangeSet'; export * from './ChangeSet';
export * from './filterName';
export * from './FreeTableGridDisplay'; export * from './FreeTableGridDisplay';
export * from './FreeTableModel'; export * from './FreeTableModel';
export * from './MacroDefinition'; export * from './MacroDefinition';

View File

@@ -1,4 +1,4 @@
import _ from 'lodash'; import _compact from 'lodash/compact';
// original C# variant // original C# variant
// public bool Match(string value) // public bool Match(string value)
@@ -39,6 +39,6 @@ export function filterName(filter: string, ...names: string[]) {
// const camelVariants = [name.replace(/[^A-Z]/g, '')] // const camelVariants = [name.replace(/[^A-Z]/g, '')]
const tokens = filter.split(' ').map(x => x.trim()); const tokens = filter.split(' ').map(x => x.trim());
return !!_.compact(names).find(name => !tokens.find(token => !name.toUpperCase().includes(token.toUpperCase()))); return !!_compact(names).find(name => !tokens.find(token => !name.toUpperCase().includes(token.toUpperCase())));
// return name.toUpperCase().includes(filter.toUpperCase()); // return name.toUpperCase().includes(filter.toUpperCase());
} }

View File

@@ -10,3 +10,4 @@ export * from './testPermission';
export * from './SqlGenerator'; export * from './SqlGenerator';
export * from './structureTools'; export * from './structureTools';
export * from './settingsExtractors'; export * from './settingsExtractors';
export * from './filterName';

View File

@@ -9,7 +9,7 @@
export let subItemsComponent = undefined; export let subItemsComponent = undefined;
export let expandOnClick = false; export let expandOnClick = false;
export let isExpandable = undefined; export let isExpandable = undefined;
export let filter; export let filter = undefined;
export let expandIconFunc = undefined; export let expandIconFunc = undefined;
export let checkedObjectsStore = null; export let checkedObjectsStore = null;
export let disableContextMenu = false; export let disableContextMenu = false;
@@ -34,6 +34,7 @@
: null; : null;
$: groups = groupFunc ? _.groupBy(listGrouped, 'group') : null; $: groups = groupFunc ? _.groupBy(listGrouped, 'group') : null;
</script> </script>
{#if groupFunc} {#if groupFunc}

View File

@@ -17,7 +17,7 @@
</script> </script>
<script lang="ts"> <script lang="ts">
import { filterName } from 'dbgate-datalib'; import { filterName } from 'dbgate-tools';
import { currentArchive } from '../stores'; import { currentArchive } from '../stores';

View File

@@ -4,7 +4,7 @@
</script> </script>
<script lang="ts"> <script lang="ts">
import { filterName } from 'dbgate-datalib'; import { filterName } from 'dbgate-tools';
import { currentArchive } from '../stores'; import { currentArchive } from '../stores';

View File

@@ -8,7 +8,7 @@
import AppObjectCore from './AppObjectCore.svelte'; import AppObjectCore from './AppObjectCore.svelte';
import { currentDatabase, extensions, getCurrentConfig, openedConnections } from '../stores'; import { currentDatabase, extensions, getCurrentConfig, openedConnections } from '../stores';
import axiosInstance from '../utility/axiosInstance'; import axiosInstance from '../utility/axiosInstance';
import { filterName } from 'dbgate-datalib'; import { filterName } from 'dbgate-tools';
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';
import ConnectionModal from '../modals/ConnectionModal.svelte'; import ConnectionModal from '../modals/ConnectionModal.svelte';
import ConfirmModal from '../modals/ConfirmModal.svelte'; import ConfirmModal from '../modals/ConfirmModal.svelte';

View File

@@ -318,7 +318,7 @@
import AppObjectCore from './AppObjectCore.svelte'; import AppObjectCore from './AppObjectCore.svelte';
import { currentDatabase, extensions, openedConnections } from '../stores'; import { currentDatabase, extensions, openedConnections } from '../stores';
import openNewTab from '../utility/openNewTab'; import openNewTab from '../utility/openNewTab';
import { filterName } from 'dbgate-datalib'; import { filterName } from 'dbgate-tools';
import { getConnectionInfo } from '../utility/metadataLoaders'; import { getConnectionInfo } from '../utility/metadataLoaders';
import fullDisplayName from '../utility/fullDisplayName'; import fullDisplayName from '../utility/fullDisplayName';
import ImportExportModal from '../modals/ImportExportModal.svelte'; import ImportExportModal from '../modals/ImportExportModal.svelte';

View File

@@ -4,7 +4,7 @@
</script> </script>
<script lang="ts"> <script lang="ts">
import { filterName } from 'dbgate-datalib'; import { filterName } from 'dbgate-tools';
import { getContext } from 'svelte'; import { getContext } from 'svelte';
import AppObjectCore from './AppObjectCore.svelte'; import AppObjectCore from './AppObjectCore.svelte';

View File

@@ -15,7 +15,7 @@
</script> </script>
<script> <script>
import { filterName } from 'dbgate-datalib'; import { filterName } from 'dbgate-tools';
import _ from 'lodash'; import _ from 'lodash';
import { onMount } from 'svelte'; import { onMount } from 'svelte';

View File

@@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import { filterName, GridDisplay } from 'dbgate-datalib'; import { GridDisplay } from 'dbgate-datalib';
import { filterName } from 'dbgate-tools';
import InlineButton from '../elements/InlineButton.svelte'; import InlineButton from '../elements/InlineButton.svelte';
import ManagerInnerContainer from '../elements/ManagerInnerContainer.svelte'; import ManagerInnerContainer from '../elements/ManagerInnerContainer.svelte';
@@ -13,6 +14,7 @@
export let isJsonView = false; export let isJsonView = false;
let filter; let filter;
</script> </script>
<SearchBoxWrapper> <SearchBoxWrapper>

View File

@@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import { filterName, GridDisplay } from 'dbgate-datalib'; import { GridDisplay } from 'dbgate-datalib';
import { filterName } from 'dbgate-tools';
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher } from 'svelte';
import InlineButton from '../elements/InlineButton.svelte'; import InlineButton from '../elements/InlineButton.svelte';
@@ -12,7 +13,7 @@
export let managerSize; export let managerSize;
export let display: GridDisplay; export let display: GridDisplay;
export let onReferenceClick = (ref) => {}; export let onReferenceClick = ref => {};
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
@@ -20,6 +21,7 @@
$: foreignKeys = display?.baseTable?.foreignKeys || []; $: foreignKeys = display?.baseTable?.foreignKeys || [];
$: dependencies = display?.baseTable?.dependencies || []; $: dependencies = display?.baseTable?.dependencies || [];
</script> </script>
<SearchBoxWrapper> <SearchBoxWrapper>
@@ -86,4 +88,5 @@
.link:hover { .link:hover {
text-decoration: underline; text-decoration: underline;
} }
</style> </style>

View File

@@ -156,7 +156,7 @@
</script> </script>
<script lang="ts"> <script lang="ts">
import { filterName } from 'dbgate-datalib'; import { filterName } from 'dbgate-tools';
import _ from 'lodash'; import _ from 'lodash';

View File

@@ -29,6 +29,7 @@
findReplace: true, findReplace: true,
executeAdditionalCondition: () => getCurrentEditor()?.hasConnection(), executeAdditionalCondition: () => getCurrentEditor()?.hasConnection(),
}); });
</script> </script>
<script lang="ts"> <script lang="ts">
@@ -143,9 +144,18 @@
} }
busy = true; busy = true;
timerLabel.start(); timerLabel.start();
const sql = selectedText || $editorValue;
await axiosInstance.post('sessions/execute-query', { await axiosInstance.post('sessions/execute-query', {
sesid, sesid,
sql: selectedText || $editorValue, sql,
});
await axiosInstance.post('query-history/write', {
data: {
sql,
conid,
database,
date: new Date().getTime(),
},
}); });
} }
@@ -233,6 +243,7 @@
{ command: 'query.replace' }, { command: 'query.replace' },
]; ];
} }
</script> </script>
<VerticalSplitter isSplitter={visibleResultTabs}> <VerticalSplitter isSplitter={visibleResultTabs}>

View File

@@ -3,9 +3,30 @@
import WidgetColumnBar from './WidgetColumnBar.svelte'; import WidgetColumnBar from './WidgetColumnBar.svelte';
import WidgetColumnBarItem from './WidgetColumnBarItem.svelte'; import WidgetColumnBarItem from './WidgetColumnBarItem.svelte';
import AppObjectList from '../appobj/AppObjectList.svelte';
import * as closedTabAppObject from '../appobj/ClosedTabAppObject.svelte';
import * as favoriteFileAppObject from '../appobj/FavoriteFileAppObject.svelte';
import { openedTabs } from '../stores';
import hasPermission from '../utility/hasPermission';
import { useFavorites } from '../utility/metadataLoaders';
import WidgetsInnerContainer from './WidgetsInnerContainer.svelte';
$: favorites = useFavorites();
</script> </script>
<WidgetColumnBar> <WidgetColumnBar>
{#if hasPermission('files/favorites/read')}
<WidgetColumnBarItem title="Favorites" name="favorites" height="20%">
<WidgetsInnerContainer>
<AppObjectList list={$favorites || []} module={favoriteFileAppObject} />
</WidgetsInnerContainer>
</WidgetColumnBarItem>
{/if}
<WidgetColumnBarItem title="Saved files" name="files"> <WidgetColumnBarItem title="Saved files" name="files">
<SavedFilesList /> <SavedFilesList />
</WidgetColumnBarItem> </WidgetColumnBarItem>

View File

@@ -14,16 +14,10 @@
import WidgetsInnerContainer from './WidgetsInnerContainer.svelte'; import WidgetsInnerContainer from './WidgetsInnerContainer.svelte';
$: favorites = useFavorites(); $: favorites = useFavorites();
</script> </script>
<WidgetColumnBar> <WidgetColumnBar>
{#if hasPermission('files/favorites/read')}
<WidgetColumnBarItem title="Favorites" name="favorites" height="20%">
<WidgetsInnerContainer>
<AppObjectList list={$favorites || []} module={favoriteFileAppObject} />
</WidgetsInnerContainer>
</WidgetColumnBarItem>
{/if}
<WidgetColumnBarItem title="Recently closed tabs" name="closedTabs"> <WidgetColumnBarItem title="Recently closed tabs" name="closedTabs">
<WidgetsInnerContainer> <WidgetsInnerContainer>
<AppObjectList <AppObjectList

View File

@@ -4,8 +4,9 @@
import DatabaseWidget from './DatabaseWidget.svelte'; import DatabaseWidget from './DatabaseWidget.svelte';
import FilesWidget from './FilesWidget.svelte'; import FilesWidget from './FilesWidget.svelte';
import PluginsWidget from './PluginsWidget.svelte'; import PluginsWidget from './PluginsWidget.svelte';
import FavoritesWidget from './FavoritesWidget.svelte'; import CellDataWidget from './CellDataWidget.svelte';
import CellDataWidget from './CellDataWidget.svelte'; import HistoryWidget from './HistoryWidget.svelte';
</script> </script>
{#if $selectedWidget == 'database'} {#if $selectedWidget == 'database'}
@@ -14,15 +15,15 @@ import CellDataWidget from './CellDataWidget.svelte';
{#if $selectedWidget == 'file'} {#if $selectedWidget == 'file'}
<FilesWidget /> <FilesWidget />
{/if} {/if}
{#if $selectedWidget == 'history'}
<HistoryWidget />
{/if}
{#if $selectedWidget == 'archive'} {#if $selectedWidget == 'archive'}
<ArchiveWidget /> <ArchiveWidget />
{/if} {/if}
{#if $selectedWidget == 'plugins'} {#if $selectedWidget == 'plugins'}
<PluginsWidget /> <PluginsWidget />
{/if} {/if}
{#if $selectedWidget == 'favorites'}
<FavoritesWidget />
{/if}
{#if $selectedWidget == 'cell-data'} {#if $selectedWidget == 'cell-data'}
<CellDataWidget /> <CellDataWidget />
{/if} {/if}

View File

@@ -18,7 +18,12 @@
{ {
icon: 'icon file', icon: 'icon file',
name: 'file', name: 'file',
title: 'Closed tabs & Saved SQL files', title: 'Favorites & Saved files',
},
{
icon: 'icon history',
name: 'history',
title: 'Query history & Closed tabs',
}, },
{ {
icon: 'icon archive', icon: 'icon archive',
@@ -30,11 +35,6 @@
name: 'plugins', name: 'plugins',
title: 'Extensions & Plugins', title: 'Extensions & Plugins',
}, },
{
icon: 'icon favorite',
name: 'favorites',
title: 'Favorites',
},
{ {
icon: 'icon cell-data', icon: 'icon cell-data',
name: 'cell-data', name: 'cell-data',

View File

@@ -4359,6 +4359,11 @@ from2@^2.1.0:
inherits "^2.0.1" inherits "^2.0.1"
readable-stream "^2.0.0" readable-stream "^2.0.0"
from@~0.1:
version "0.1.7"
resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=
fs-constants@^1.0.0: fs-constants@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
@@ -4408,6 +4413,13 @@ fs-minipass@^2.0.0, fs-minipass@^2.1.0:
dependencies: dependencies:
minipass "^3.0.0" minipass "^3.0.0"
fs-reverse@^0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/fs-reverse/-/fs-reverse-0.0.3.tgz#5ef1e180a65fc0ee3cfb972d376114814203b43d"
integrity sha512-zu+5yhmaWueDBAWm7y6ejj2PipVep3EQlQYdfS6r3zsfzIfTVkcdbrsqye2UovisDqogu5dJFxae/dUAOYQqBA==
dependencies:
from "~0.1"
fs-write-stream-atomic@^1.0.8: fs-write-stream-atomic@^1.0.8:
version "1.0.10" version "1.0.10"
resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9"