Fix drop/drop cascade for partitioned tables. Fixes #2550

This commit is contained in:
Akshay Joshi 2017-07-10 16:02:32 +01:00 committed by Dave Page
parent 7aa7ea0fe2
commit f06c3578f6
7 changed files with 108 additions and 41 deletions

View File

@ -1009,12 +1009,6 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings):
scid: Schema ID scid: Schema ID
tid: Table ID tid: Table ID
""" """
# Below will decide if it's simple drop or drop with cascade call
if self.cmd == 'delete':
# This is a cascade operation
cascade = True
else:
cascade = False
try: try:
SQL = render_template( SQL = render_template(
@ -1037,25 +1031,7 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings):
) )
) )
data = res['rows'][0] return super(TableView, self).delete(gid, sid, did, scid, tid, res)
SQL = render_template(
"/".join([self.table_template_path, 'delete.sql']),
data=data, cascade=cascade,
conn=self.conn
)
status, res = self.conn.execute_scalar(SQL)
if not status:
return internal_server_error(errormsg=res)
return make_json_response(
success=1,
info=gettext("Table dropped"),
data={
'id': tid,
'scid': scid
}
)
except Exception as e: except Exception as e:
return internal_server_error(errormsg=str(e)) return internal_server_error(errormsg=str(e))

View File

@ -179,6 +179,7 @@ class PartitionsView(BaseTableView, DataTypeReader, VacuumSettings):
{'get': 'properties', 'delete': 'delete', 'put': 'update'}, {'get': 'properties', 'delete': 'delete', 'put': 'update'},
{'get': 'list', 'post': 'create'} {'get': 'list', 'post': 'create'}
], ],
'delete': [{'delete': 'delete'}],
'nodes': [{'get': 'nodes'}, {'get': 'nodes'}], 'nodes': [{'get': 'nodes'}, {'get': 'nodes'}],
'children': [{'get': 'children'}], 'children': [{'get': 'children'}],
'sql': [{'get': 'sql'}], 'sql': [{'get': 'sql'}],
@ -579,5 +580,45 @@ class PartitionsView(BaseTableView, DataTypeReader, VacuumSettings):
except Exception as e: except Exception as e:
return internal_server_error(errormsg=str(e)) return internal_server_error(errormsg=str(e))
@BaseTableView.check_precondition
def delete(self, gid, sid, did, scid, tid, ptid):
"""
This function will delete the table object
Args:
gid: Server Group ID
sid: Server ID
did: Database ID
scid: Schema ID
tid: Table ID
"""
try:
SQL = render_template(
"/".join([self.partition_template_path, 'properties.sql']),
did=did, scid=scid, tid=tid,ptid=ptid,
datlastsysoid=self.datlastsysoid
)
status, res = self.conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=res)
if not res['rows']:
return make_json_response(
success=0,
errormsg=gettext(
'Error: Object not found.'
),
info=gettext(
'The specified partition could not be found.\n'
)
)
return super(PartitionsView, self).delete(
gid, sid, did, scid, tid, res)
except Exception as e:
return internal_server_error(errormsg=str(e))
PartitionsView.register_node_view(blueprint) PartitionsView.register_node_view(blueprint)

View File

@ -1,9 +1,10 @@
define([ define([
'sources/gettext', 'sources/url_for', 'jquery', 'underscore', 'sources/gettext', 'sources/url_for', 'jquery', 'underscore',
'underscore.string', 'pgadmin', 'pgadmin.browser', 'backform', 'alertify', 'underscore.string', 'pgadmin', 'pgadmin.browser', 'backform', 'alertify',
'sources/alerts/alertify_wrapper',
'pgadmin.browser.collection', 'pgadmin.browser.table.partition.utils' 'pgadmin.browser.collection', 'pgadmin.browser.table.partition.utils'
], ],
function(gettext, url_for, $, _, S, pgAdmin, pgBrowser, Backform, alertify) { function(gettext, url_for, $, _, S, pgAdmin, pgBrowser, Backform, alertify, AlertifyWrapper) {
if (!pgBrowser.Nodes['coll-partition']) { if (!pgBrowser.Nodes['coll-partition']) {
var databases = pgAdmin.Browser.Nodes['coll-partition'] = var databases = pgAdmin.Browser.Nodes['coll-partition'] =
@ -163,7 +164,8 @@ function(gettext, url_for, $, _, S, pgAdmin, pgBrowser, Backform, alertify) {
dataType: "json", dataType: "json",
success: function(res) { success: function(res) {
if (res.success == 1) { if (res.success == 1) {
alertify.success(res.info); var alertifyWrapper = new AlertifyWrapper();
alertifyWrapper.success(res.info);
t.unload(i); t.unload(i);
t.setInode(i); t.setInode(i);
t.deselect(i); t.deselect(i);
@ -176,7 +178,8 @@ function(gettext, url_for, $, _, S, pgAdmin, pgBrowser, Backform, alertify) {
try { try {
var err = $.parseJSON(xhr.responseText); var err = $.parseJSON(xhr.responseText);
if (err.success == 0) { if (err.success == 0) {
alertify.error(err.errormsg); var alertifyWrapper = new AlertifyWrapper();
alertifyWrapper.error(err.errormsg);
} }
} catch (e) {} } catch (e) {}
t.unload(i); t.unload(i);
@ -216,9 +219,10 @@ function(gettext, url_for, $, _, S, pgAdmin, pgBrowser, Backform, alertify) {
dataType: "json", dataType: "json",
success: function(res) { success: function(res) {
if (res.success == 1) { if (res.success == 1) {
alertify.success(res.info); var alertifyWrapper = new AlertifyWrapper();
alertifyWrapper.success(res.info);
t.removeIcon(i); t.removeIcon(i);
data.icon = 'icon-table'; data.icon = 'icon-partition';
t.addIcon(i, {icon: data.icon}); t.addIcon(i, {icon: data.icon});
t.unload(i); t.unload(i);
t.setInode(i); t.setInode(i);
@ -233,7 +237,8 @@ function(gettext, url_for, $, _, S, pgAdmin, pgBrowser, Backform, alertify) {
try { try {
var err = $.parseJSON(xhr.responseText); var err = $.parseJSON(xhr.responseText);
if (err.success == 0) { if (err.success == 0) {
alertify.error(err.errormsg); var alertifyWrapper = new AlertifyWrapper();
alertifyWrapper.error(err.errormsg);
} }
} catch (e) {} } catch (e) {}
t.unload(i); t.unload(i);
@ -264,9 +269,10 @@ function(gettext, url_for, $, _, S, pgAdmin, pgBrowser, Backform, alertify) {
type:'DELETE', type:'DELETE',
success: function(res) { success: function(res) {
if (res.success == 1) { if (res.success == 1) {
alertify.success(res.info); var alertifyWrapper = new AlertifyWrapper();
alertifyWrapper.success(res.info);
t.removeIcon(i); t.removeIcon(i);
data.icon = 'icon-table'; data.icon = 'icon-partition';
t.addIcon(i, {icon: data.icon}); t.addIcon(i, {icon: data.icon});
t.unload(i); t.unload(i);
t.setInode(i); t.setInode(i);
@ -281,7 +287,8 @@ function(gettext, url_for, $, _, S, pgAdmin, pgBrowser, Backform, alertify) {
try { try {
var err = $.parseJSON(xhr.responseText); var err = $.parseJSON(xhr.responseText);
if (err.success == 0) { if (err.success == 0) {
alertify.error(err.errormsg); var alertifyWrapper = new AlertifyWrapper();
alertifyWrapper.error(err.errormsg);
} }
} catch (e) {} } catch (e) {}
t.unload(i); t.unload(i);
@ -313,7 +320,8 @@ function(gettext, url_for, $, _, S, pgAdmin, pgBrowser, Backform, alertify) {
type:'PUT', type:'PUT',
success: function(res) { success: function(res) {
if (res.success == 1) { if (res.success == 1) {
alertify.success(res.info); var alertifyWrapper = new AlertifyWrapper();
alertifyWrapper.success(res.info);
var n = t.next(i); var n = t.next(i);
if (!n || !n.length) { if (!n || !n.length) {
n = t.prev(i); n = t.prev(i);
@ -332,7 +340,8 @@ function(gettext, url_for, $, _, S, pgAdmin, pgBrowser, Backform, alertify) {
try { try {
var err = $.parseJSON(xhr.responseText); var err = $.parseJSON(xhr.responseText);
if (err.success == 0) { if (err.success == 0) {
alertify.error(err.errormsg); var alertifyWrapper = new AlertifyWrapper();
alertifyWrapper.error(err.errormsg);
} }
} catch (e) {} } catch (e) {}
} }

View File

@ -172,6 +172,7 @@ define('pgadmin.node.table', [
return false; return false;
alertify.confirm( alertify.confirm(
gettext('Truncate Table'),
S(gettext('Are you sure you want to truncate table %s?')).sprintf(d.label).value(), S(gettext('Are you sure you want to truncate table %s?')).sprintf(d.label).value(),
function (e) { function (e) {
if (e) { if (e) {
@ -186,7 +187,7 @@ define('pgadmin.node.table', [
var alertifyWrapper = new AlertifyWrapper(); var alertifyWrapper = new AlertifyWrapper();
alertifyWrapper.success(res.info); alertifyWrapper.success(res.info);
t.removeIcon(i); t.removeIcon(i);
data.icon = 'icon-table'; data.icon = data.is_partitioned ? 'icon-partition': 'icon-table';
t.addIcon(i, {icon: data.icon}); t.addIcon(i, {icon: data.icon});
t.unload(i); t.unload(i);
t.setInode(i); t.setInode(i);
@ -209,7 +210,8 @@ define('pgadmin.node.table', [
} }
}); });
} }
}); }, function() {}
);
}, },
reset_table_stats: function(args) { reset_table_stats: function(args) {
var input = args || {}, var input = args || {},
@ -235,7 +237,7 @@ define('pgadmin.node.table', [
var alertifyWrapper = new AlertifyWrapper(); var alertifyWrapper = new AlertifyWrapper();
alertifyWrapper.success(res.info); alertifyWrapper.success(res.info);
t.removeIcon(i); t.removeIcon(i);
data.icon = 'icon-table'; data.icon = data.is_partitioned ? 'icon-partition': 'icon-table';
t.addIcon(i, {icon: data.icon}); t.addIcon(i, {icon: data.icon});
t.unload(i); t.unload(i);
t.setInode(i); t.setInode(i);

View File

@ -52,7 +52,7 @@ SELECT rel.oid, rel.relname AS name, rel.reltablespace AS spcoid,rel.relacl AS r
array_to_string(rel.reloptions, ',') AS table_vacuum_settings_str, array_to_string(rel.reloptions, ',') AS table_vacuum_settings_str,
array_to_string(tst.reloptions, ',') AS toast_table_vacuum_settings_str, array_to_string(tst.reloptions, ',') AS toast_table_vacuum_settings_str,
rel.reloptions AS reloptions, tst.reloptions AS toast_reloptions, rel.reloftype, rel.reloptions AS reloptions, tst.reloptions AS toast_reloptions, rel.reloftype,
(select quote_ident(nspname) FROM pg_namespace WHERE oid = {{scid}}::oid )||'.'||quote_ident(typ.typname) AS typname, CASE WHEN typ.typname IS NOT NULL THEN (select quote_ident(nspname) FROM pg_namespace WHERE oid = {{scid}}::oid )||'.'||quote_ident(typ.typname) ELSE typ.typname END AS typname,
(CASE WHEN rel.reltoastrelid = 0 THEN false ELSE true END) AS hastoasttable, (CASE WHEN rel.reltoastrelid = 0 THEN false ELSE true END) AS hastoasttable,
-- Added for pgAdmin4 -- Added for pgAdmin4
(CASE WHEN (substring(array_to_string(rel.reloptions, ',') FROM 'autovacuum_enabled=([a-z|0-9]*)'))::boolean THEN true ELSE false END) AS autovacuum_custom, (CASE WHEN (substring(array_to_string(rel.reloptions, ',') FROM 'autovacuum_enabled=([a-z|0-9]*)'))::boolean THEN true ELSE false END) AS autovacuum_custom,

View File

@ -51,7 +51,7 @@ SELECT rel.oid, rel.relname AS name, rel.reltablespace AS spcoid,rel.relacl AS r
array_to_string(rel.reloptions, ',') AS table_vacuum_settings_str, array_to_string(rel.reloptions, ',') AS table_vacuum_settings_str,
array_to_string(tst.reloptions, ',') AS toast_table_vacuum_settings_str, array_to_string(tst.reloptions, ',') AS toast_table_vacuum_settings_str,
rel.reloptions AS reloptions, tst.reloptions AS toast_reloptions, rel.reloftype, rel.reloptions AS reloptions, tst.reloptions AS toast_reloptions, rel.reloftype,
(select quote_ident(nspname) FROM pg_namespace WHERE oid = {{scid}}::oid )||'.'||quote_ident(typ.typname) AS typname, CASE WHEN typ.typname IS NOT NULL THEN (select quote_ident(nspname) FROM pg_namespace WHERE oid = {{scid}}::oid )||'.'||quote_ident(typ.typname) ELSE typ.typname END AS typname,
(CASE WHEN rel.reltoastrelid = 0 THEN false ELSE true END) AS hastoasttable, (CASE WHEN rel.reltoastrelid = 0 THEN false ELSE true END) AS hastoasttable,
-- Added for pgAdmin4 -- Added for pgAdmin4
(CASE WHEN (substring(array_to_string(rel.reloptions, ',') FROM 'autovacuum_enabled=([a-z|0-9]*)'))::boolean THEN true ELSE false END) AS autovacuum_custom, (CASE WHEN (substring(array_to_string(rel.reloptions, ',') FROM 'autovacuum_enabled=([a-z|0-9]*)'))::boolean THEN true ELSE false END) AS autovacuum_custom,

View File

@ -2084,6 +2084,45 @@ class BaseTableView(PGChildNodeView):
} }
) )
def delete(self, gid, sid, did, scid, tid, res):
"""
This function will delete the table object
Args:
gid: Server Group ID
sid: Server ID
did: Database ID
scid: Schema ID
tid: Table ID
"""
# Below will decide if it's simple drop or drop with cascade call
if self.cmd == 'delete':
# This is a cascade operation
cascade = True
else:
cascade = False
data = res['rows'][0]
SQL = render_template(
"/".join([self.table_template_path, 'delete.sql']),
data=data, cascade=cascade,
conn=self.conn
)
status, res = self.conn.execute_scalar(SQL)
if not status:
return internal_server_error(errormsg=res)
return make_json_response(
success=1,
info=gettext("Table dropped"),
data={
'id': tid,
'scid': scid
}
)
def get_schema_and_table_name(self, tid): def get_schema_and_table_name(self, tid):
""" """
This function will fetch the schema qualified name of the This function will fetch the schema qualified name of the