mirror of
https://github.com/dbgate/dbgate
synced 2024-11-07 20:26:23 +00:00
Materialized views #123
This commit is contained in:
parent
93edcc4d0a
commit
35fc2e0f5b
@ -293,6 +293,20 @@ export class SqlDumper {
|
|||||||
changeViewSchema(obj: ViewInfo, newSchema: string) {}
|
changeViewSchema(obj: ViewInfo, newSchema: string) {}
|
||||||
renameView(obj: ViewInfo, newSchema: string) {}
|
renameView(obj: ViewInfo, newSchema: string) {}
|
||||||
|
|
||||||
|
createMatview(obj: ViewInfo) {
|
||||||
|
this.putRaw(obj.createSql);
|
||||||
|
this.endCommand();
|
||||||
|
}
|
||||||
|
dropMatview(obj: ViewInfo, { testIfExists = false }) {
|
||||||
|
this.putCmd('^drop ^materialized ^view %f', obj);
|
||||||
|
}
|
||||||
|
alterMatview(obj: ViewInfo) {
|
||||||
|
this.putRaw(obj.createSql.replace(/create\s+view/i, 'ALTER VIEW'));
|
||||||
|
this.endCommand();
|
||||||
|
}
|
||||||
|
changeMatviewSchema(obj: ViewInfo, newSchema: string) {}
|
||||||
|
renameMatview(obj: ViewInfo, newSchema: string) {}
|
||||||
|
|
||||||
createProcedure(obj: ProcedureInfo) {
|
createProcedure(obj: ProcedureInfo) {
|
||||||
this.putRaw(obj.createSql);
|
this.putRaw(obj.createSql);
|
||||||
this.endCommand();
|
this.endCommand();
|
||||||
|
@ -30,6 +30,10 @@ interface SqlGeneratorOptions {
|
|||||||
checkIfViewExists: boolean;
|
checkIfViewExists: boolean;
|
||||||
createViews: boolean;
|
createViews: boolean;
|
||||||
|
|
||||||
|
dropMatviews: boolean;
|
||||||
|
checkIfMatviewExists: boolean;
|
||||||
|
createMatviews: boolean;
|
||||||
|
|
||||||
dropProcedures: boolean;
|
dropProcedures: boolean;
|
||||||
checkIfProcedureExists: boolean;
|
checkIfProcedureExists: boolean;
|
||||||
createProcedures: boolean;
|
createProcedures: boolean;
|
||||||
@ -52,6 +56,7 @@ interface SqlGeneratorObject {
|
|||||||
export class SqlGenerator {
|
export class SqlGenerator {
|
||||||
private tables: TableInfo[];
|
private tables: TableInfo[];
|
||||||
private views: ViewInfo[];
|
private views: ViewInfo[];
|
||||||
|
private matviews: ViewInfo[];
|
||||||
private procedures: ProcedureInfo[];
|
private procedures: ProcedureInfo[];
|
||||||
private functions: FunctionInfo[];
|
private functions: FunctionInfo[];
|
||||||
private triggers: TriggerInfo[];
|
private triggers: TriggerInfo[];
|
||||||
@ -70,6 +75,7 @@ export class SqlGenerator {
|
|||||||
this.dbinfo = extendDatabaseInfo(dbinfo);
|
this.dbinfo = extendDatabaseInfo(dbinfo);
|
||||||
this.tables = this.extract('tables');
|
this.tables = this.extract('tables');
|
||||||
this.views = this.extract('views');
|
this.views = this.extract('views');
|
||||||
|
this.matviews = this.extract('matviews');
|
||||||
this.procedures = this.extract('procedures');
|
this.procedures = this.extract('procedures');
|
||||||
this.functions = this.extract('functions');
|
this.functions = this.extract('functions');
|
||||||
this.triggers = this.extract('triggers');
|
this.triggers = this.extract('triggers');
|
||||||
@ -90,6 +96,8 @@ export class SqlGenerator {
|
|||||||
if (this.checkDumper()) return;
|
if (this.checkDumper()) return;
|
||||||
this.dropObjects(this.views, 'View');
|
this.dropObjects(this.views, 'View');
|
||||||
if (this.checkDumper()) return;
|
if (this.checkDumper()) return;
|
||||||
|
this.dropObjects(this.matviews, 'Matview');
|
||||||
|
if (this.checkDumper()) return;
|
||||||
this.dropObjects(this.triggers, 'Trigger');
|
this.dropObjects(this.triggers, 'Trigger');
|
||||||
if (this.checkDumper()) return;
|
if (this.checkDumper()) return;
|
||||||
|
|
||||||
@ -114,6 +122,8 @@ export class SqlGenerator {
|
|||||||
if (this.checkDumper()) return;
|
if (this.checkDumper()) return;
|
||||||
this.createObjects(this.views, 'View');
|
this.createObjects(this.views, 'View');
|
||||||
if (this.checkDumper()) return;
|
if (this.checkDumper()) return;
|
||||||
|
this.createObjects(this.matviews, 'Matview');
|
||||||
|
if (this.checkDumper()) return;
|
||||||
this.createObjects(this.triggers, 'Trigger');
|
this.createObjects(this.triggers, 'Trigger');
|
||||||
if (this.checkDumper()) return;
|
if (this.checkDumper()) return;
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
import { getFormContext } from '../forms/FormProviderCore.svelte';
|
import { getFormContext } from '../forms/FormProviderCore.svelte';
|
||||||
import FormSelectField from '../forms/FormSelectField.svelte';
|
import FormSelectField from '../forms/FormSelectField.svelte';
|
||||||
|
import { getObjectTypeFieldLabel } from '../utility/common';
|
||||||
import { useDatabaseInfo, useDatabaseList } from '../utility/metadataLoaders';
|
import { useDatabaseInfo, useDatabaseList } from '../utility/metadataLoaders';
|
||||||
|
|
||||||
export let conidName;
|
export let conidName;
|
||||||
@ -15,19 +16,25 @@
|
|||||||
const { values, setFieldValue } = getFormContext();
|
const { values, setFieldValue } = getFormContext();
|
||||||
$: dbinfo = useDatabaseInfo({ conid: $values[conidName], database: $values[databaseName] });
|
$: dbinfo = useDatabaseInfo({ conid: $values[conidName], database: $values[databaseName] });
|
||||||
|
|
||||||
$: tablesOptions = _.compact([...($dbinfo?.tables || []), ...($dbinfo?.views || []), ...($dbinfo?.collections || [])])
|
$: tablesOptions = _.compact([
|
||||||
|
...($dbinfo?.tables || []),
|
||||||
|
...($dbinfo?.views || []),
|
||||||
|
...($dbinfo?.matviews || []),
|
||||||
|
...($dbinfo?.collections || []),
|
||||||
|
])
|
||||||
.filter(x => !$values[schemaName] || x.schemaName == $values[schemaName])
|
.filter(x => !$values[schemaName] || x.schemaName == $values[schemaName])
|
||||||
.map(x => ({
|
.map(x => ({
|
||||||
value: x.pureName,
|
value: x.pureName,
|
||||||
label: x.pureName,
|
label: x.pureName,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<FormSelectField {...$$restProps} {name} options={tablesOptions} isMulti templateProps={{ noMargin: true }} />
|
<FormSelectField {...$$restProps} {name} options={tablesOptions} isMulti templateProps={{ noMargin: true }} />
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{#each ['tables', 'views', 'collections'] as field}
|
{#each ['tables', 'views', 'matviews', 'collections'] as field}
|
||||||
{#if $dbinfo && $dbinfo[field]?.length > 0}
|
{#if $dbinfo && $dbinfo[field]?.length > 0}
|
||||||
<FormStyledButton
|
<FormStyledButton
|
||||||
type="button"
|
type="button"
|
||||||
@ -49,4 +56,5 @@
|
|||||||
.wrapper {
|
.wrapper {
|
||||||
margin: var(--dim-large-form-margin);
|
margin: var(--dim-large-form-margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
import openNewTab from '../utility/openNewTab';
|
import openNewTab from '../utility/openNewTab';
|
||||||
import ErrorInfo from '../elements/ErrorInfo.svelte';
|
import ErrorInfo from '../elements/ErrorInfo.svelte';
|
||||||
import LoadingInfo from '../elements/LoadingInfo.svelte';
|
import LoadingInfo from '../elements/LoadingInfo.svelte';
|
||||||
|
import { getObjectTypeFieldLabel } from '../utility/common';
|
||||||
|
|
||||||
export let conid;
|
export let conid;
|
||||||
export let database;
|
export let database;
|
||||||
@ -49,8 +50,6 @@
|
|||||||
|
|
||||||
export let initialObjects = null;
|
export let initialObjects = null;
|
||||||
|
|
||||||
const OBJ_TYPE_LABELS = { Matview: 'Materialized view' };
|
|
||||||
|
|
||||||
let busy = false;
|
let busy = false;
|
||||||
let managerSize;
|
let managerSize;
|
||||||
let objectsFilter = '';
|
let objectsFilter = '';
|
||||||
@ -156,7 +155,7 @@
|
|||||||
<AppObjectList
|
<AppObjectList
|
||||||
list={objectList.map(x => ({ ...x, conid, database }))}
|
list={objectList.map(x => ({ ...x, conid, database }))}
|
||||||
module={databaseObjectAppObject}
|
module={databaseObjectAppObject}
|
||||||
groupFunc={data => _.startCase(data.objectTypeField)}
|
groupFunc={data => getObjectTypeFieldLabel(data.objectTypeField)}
|
||||||
isExpandable={data => data.objectTypeField == 'tables' || data.objectTypeField == 'views'}
|
isExpandable={data => data.objectTypeField == 'tables' || data.objectTypeField == 'views'}
|
||||||
filter={objectsFilter}
|
filter={objectsFilter}
|
||||||
disableContextMenu
|
disableContextMenu
|
||||||
@ -215,8 +214,8 @@
|
|||||||
|
|
||||||
<FormCheckboxField label="Truncate tables (delete all rows)" name="truncate" />
|
<FormCheckboxField label="Truncate tables (delete all rows)" name="truncate" />
|
||||||
|
|
||||||
{#each ['View', 'MatView', 'Procedure', 'Function', 'Trigger'] as objtype}
|
{#each ['View', 'Matview', 'Procedure', 'Function', 'Trigger'] as objtype}
|
||||||
<div class="obj-heading">{OBJ_TYPE_LABELS[objtype] || objtype}s</div>
|
<div class="obj-heading">{getObjectTypeFieldLabel(objtype.toLowerCase() + 's')}s</div>
|
||||||
<FormCheckboxField label="Create" name={`create${objtype}s`} />
|
<FormCheckboxField label="Create" name={`create${objtype}s`} />
|
||||||
<FormCheckboxField label="Drop" name={`drop${objtype}s`} />
|
<FormCheckboxField label="Drop" name={`drop${objtype}s`} />
|
||||||
{#if values[`drop${objtype}s`]}
|
{#if values[`drop${objtype}s`]}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { openedTabs } from '../stores';
|
import { openedTabs } from '../stores';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
export class LoadingToken {
|
export class LoadingToken {
|
||||||
isCanceled = false;
|
isCanceled = false;
|
||||||
@ -26,3 +27,8 @@ export function setSelectedTabFunc(files, tabid) {
|
|||||||
export function setSelectedTab(tabid) {
|
export function setSelectedTab(tabid) {
|
||||||
openedTabs.update(tabs => setSelectedTabFunc(tabs, tabid));
|
openedTabs.update(tabs => setSelectedTabFunc(tabs, tabid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getObjectTypeFieldLabel(objectTypeField) {
|
||||||
|
if (objectTypeField == 'matviews') return 'Materialized Views';
|
||||||
|
return _.startCase(objectTypeField);
|
||||||
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
import ErrorInfo from '../elements/ErrorInfo.svelte';
|
import ErrorInfo from '../elements/ErrorInfo.svelte';
|
||||||
import axiosInstance from '../utility/axiosInstance';
|
import axiosInstance from '../utility/axiosInstance';
|
||||||
import LoadingInfo from '../elements/LoadingInfo.svelte';
|
import LoadingInfo from '../elements/LoadingInfo.svelte';
|
||||||
|
import { getObjectTypeFieldLabel } from '../utility/common';
|
||||||
|
|
||||||
export let conid;
|
export let conid;
|
||||||
export let database;
|
export let database;
|
||||||
@ -36,8 +37,6 @@
|
|||||||
axiosInstance.post('database-connections/refresh', { conid, database });
|
axiosInstance.post('database-connections/refresh', { conid, database });
|
||||||
};
|
};
|
||||||
|
|
||||||
const OBJECT_TYPE_LABELS = { matviews: 'Materialized views' };
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $status && $status.name == 'error'}
|
{#if $status && $status.name == 'error'}
|
||||||
@ -65,7 +64,7 @@
|
|||||||
<AppObjectList
|
<AppObjectList
|
||||||
list={objectList.map(x => ({ ...x, conid, database }))}
|
list={objectList.map(x => ({ ...x, conid, database }))}
|
||||||
module={databaseObjectAppObject}
|
module={databaseObjectAppObject}
|
||||||
groupFunc={data => OBJECT_TYPE_LABELS[data.objectTypeField] || _.startCase(data.objectTypeField)}
|
groupFunc={data => getObjectTypeFieldLabel(data.objectTypeField)}
|
||||||
subItemsComponent={SubColumnParamList}
|
subItemsComponent={SubColumnParamList}
|
||||||
isExpandable={data =>
|
isExpandable={data =>
|
||||||
data.objectTypeField == 'tables' || data.objectTypeField == 'views' || data.objectTypeField == 'matviews'}
|
data.objectTypeField == 'tables' || data.objectTypeField == 'views' || data.objectTypeField == 'matviews'}
|
||||||
|
Loading…
Reference in New Issue
Block a user