mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Fix drop/drop cascade for partitioned tables. Fixes #2550
This commit is contained in:
parent
7aa7ea0fe2
commit
f06c3578f6
@ -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))
|
||||||
|
@ -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)
|
||||||
|
@ -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) {}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user