Materialized views #123

This commit is contained in:
Jan Prochazka 2021-05-30 10:13:38 +02:00
parent 93edcc4d0a
commit 35fc2e0f5b
6 changed files with 46 additions and 10 deletions

View File

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

View File

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

View File

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

View File

@ -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`]}

View File

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

View File

@ -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'}