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

REL-1_X
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
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:
SQL = render_template(
@ -1037,25 +1031,7 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings):
)
)
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
}
)
return super(TableView, self).delete(gid, sid, did, scid, tid, res)
except Exception as 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': 'list', 'post': 'create'}
],
'delete': [{'delete': 'delete'}],
'nodes': [{'get': 'nodes'}, {'get': 'nodes'}],
'children': [{'get': 'children'}],
'sql': [{'get': 'sql'}],
@ -579,5 +580,45 @@ class PartitionsView(BaseTableView, DataTypeReader, VacuumSettings):
except Exception as 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)

View File

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

View File

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

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(tst.reloptions, ',') AS toast_table_vacuum_settings_str,
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,
-- 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,

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):
"""
This function will fetch the schema qualified name of the