Support Enable Always and Enable Replica on triggers. Fixes #4006

This commit is contained in:
Aditya Toshniwal 2019-11-01 11:49:17 +00:00 committed by Dave Page
parent ab5d954337
commit 131a944e24
39 changed files with 131 additions and 86 deletions

View File

@ -24,6 +24,13 @@ Use the fields in the *General* tab to identify the compound trigger:
The name will be displayed in the *pgAdmin* tree control.
* Store notes about the compound trigger in the *Comment* field.
.. image:: images/compound_trigger_general_enabled.png
:alt: Trigger enabled in dialog tab
:align: center
* *Trigger enabled* field is available in compound trigger dialog once the trigger is created.
You can select one of the four options available.
Click the *Events* tab to continue.
.. image:: images/compound_trigger_events.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View File

@ -11,6 +11,7 @@ New features
| `Issue #1974 <https://redmine.postgresql.org/issues/1974>`_ - Added encrypted password in reverse engineered SQL for roles.
| `Issue #4351 <https://redmine.postgresql.org/issues/4351>`_ - Add an option to request confirmation before cancelling changes on a Properties dialog.
| `Issue #4006 <https://redmine.postgresql.org/issues/4006>`_ - Support Enable Always and Enable Replica on triggers.
Housekeeping
************

View File

@ -48,6 +48,13 @@ Use the fields in the *Definition* tab to define the trigger:
arguments to the function when the trigger is executed. The arguments are
literal string constants.
.. image:: images/trigger_definition_enabled.png
:alt: Trigger enabled in dialog tab
:align: center
* *Trigger enabled* field is available in trigger dialog once the trigger is created.
You can select one of the four options available.
Click the *Events* tab to continue.
.. image:: images/trigger_events.png
@ -96,4 +103,4 @@ The example demonstrates creating a trigger named *log_update*.
* Click the *Info* button (i) to access online help.
* Click the *Save* button to save work.
* Click the *Cancel* button to exit without saving work.
* Click the *Reset* button to restore configuration parameters.
* Click the *Reset* button to restore configuration parameters.

View File

@ -1228,7 +1228,7 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings):
request.data, encoding='utf-8'
)
# Convert str 'true' to boolean type
is_enable = json.loads(data['enable'])
is_enable_trigger = data['is_enable_trigger']
try:
SQL = render_template(
@ -1245,7 +1245,7 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings):
"/".join([
self.table_template_path, 'enable_disable_trigger.sql'
]),
data=data, is_enable_trigger=is_enable
data=data, is_enable_trigger=is_enable_trigger
)
status, res = self.conn.execute_scalar(SQL)
if not status:
@ -1253,8 +1253,9 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings):
return make_json_response(
success=1,
info=gettext("Trigger(s) have been enabled") if is_enable
else gettext("Trigger(s) have been disabled"),
info=gettext("Trigger(s) have been disabled")
if is_enable_trigger == 'D'
else gettext("Trigger(s) have been enabled"),
data={
'id': tid,
'scid': scid

View File

@ -372,9 +372,9 @@ class CompoundTriggerView(PGChildNodeView):
rset['rows'][0]['oid'],
tid,
rset['rows'][0]['name'],
icon="icon-compound_trigger" if
rset['rows'][0]['is_enable_trigger'] else
"icon-compound_trigger-bad"
icon="icon-compound_trigger-bad" if
rset['rows'][0]['is_enable_trigger'] == 'D' else
"icon-compound_trigger"
)
return make_json_response(
@ -412,8 +412,9 @@ class CompoundTriggerView(PGChildNodeView):
row['oid'],
tid,
row['name'],
icon="icon-compound_trigger" if row['is_enable_trigger']
else "icon-compound_trigger-bad"
icon="icon-compound_trigger-bad"
if row['is_enable_trigger'] == 'D'
else "icon-compound_trigger"
))
return make_json_response(
@ -736,9 +737,9 @@ class CompoundTriggerView(PGChildNodeView):
new_trid,
tid,
name,
icon="icon-%s" % self.node_type if
data['is_enable_trigger'] else
"icon-%s-bad" % self.node_type
icon="icon-%s-bad" % self.node_type if
data['is_enable_trigger'] == 'D' else
"icon-%s" % self.node_type
)
)
except Exception as e:
@ -889,7 +890,7 @@ class CompoundTriggerView(PGChildNodeView):
SQL = sql_header + '\n\n' + SQL.strip('\n')
# If compound trigger is disbaled then add sql code for the same
if not data['is_enable_trigger']:
if data['is_enable_trigger'] != 'O':
SQL += '\n\n'
SQL += render_template("/".join([self.template_path,
'enable_disable_trigger.sql']),
@ -917,7 +918,7 @@ class CompoundTriggerView(PGChildNodeView):
)
# Convert str 'true' to boolean type
is_enable_flag = json.loads(data['enable'])
is_enable_trigger = data['is_enable_trigger']
try:
@ -940,7 +941,7 @@ class CompoundTriggerView(PGChildNodeView):
# current compound trigger which is disabled already so we need to
# alter the 'is_enable_trigger' flag so that we can render
# correct SQL for operation
o_data['is_enable_trigger'] = is_enable_flag
o_data['is_enable_trigger'] = is_enable_trigger
# Adding parent into data dict, will be using it while creating sql
o_data['schema'] = self.schema

View File

@ -108,7 +108,7 @@ define('pgadmin.node.compound_trigger', [
$.ajax({
url: obj.generate_url(i, 'enable' , d, true),
type:'PUT',
data: {'enable' : true},
data: {'is_enable_trigger' : 'O'},
dataType: 'json',
})
.done(function(res) {
@ -146,7 +146,7 @@ define('pgadmin.node.compound_trigger', [
$.ajax({
url: obj.generate_url(i, 'enable' , d, true),
type:'PUT',
data: {'enable' : false},
data: {'is_enable_trigger' : 'D'},
dataType: 'json',
})
.done(function(res) {
@ -185,13 +185,20 @@ define('pgadmin.node.compound_trigger', [
type: 'int', disabled: true, mode: ['properties'],
},{
id: 'is_enable_trigger', label: gettext('Trigger enabled?'),
type: 'switch', mode: ['edit', 'properties'],
mode: ['edit', 'properties'],
disabled: function() {
if(this.node_info && ('catalog' in this.node_info || 'view' in this.node_info)) {
return true;
}
return false;
},
options: [
{label: 'Enable', value: 'O'},
{label: 'Enable Replica', value: 'R'},
{label: 'Enable Always', value: 'A'},
{label: 'Disable', value: 'D'},
],
control: 'select2', select2: { allowClear: false, width: '100%' },
},{
type: 'nested', control: 'fieldset', mode: ['create','edit', 'properties'],
label: gettext('FOR Events'), group: gettext('Events'), contentClass: 'row',

View File

@ -45,12 +45,20 @@ class CompoundTriggersUpdateTestCase(BaseTestGenerator):
})),
('Enable compound trigger',
dict(url='/browser/compound_trigger/obj/',
data={"is_enable_trigger": True},
data={"is_enable_trigger": 'O'},
disable_trigger=True
)),
('Enable always compound trigger',
dict(url='/browser/compound_trigger/obj/',
data={"is_enable_trigger": 'A'}
)),
('Enable replica compound trigger',
dict(url='/browser/compound_trigger/obj/',
data={"is_enable_trigger": 'R'}
)),
('Disable compound trigger',
dict(url='/browser/compound_trigger/obj/',
data={"is_enable_trigger": False}
data={"is_enable_trigger": 'D'}
)),
]

View File

@ -10,10 +10,10 @@
import axios from 'axios';
export function disableTriggers(tree, alertify, generateUrl, args) {
return setTriggers(tree, alertify, generateUrl, args, {enable: 'false' });
return setTriggers(tree, alertify, generateUrl, args, {is_enable_trigger: 'D' });
}
export function enableTriggers(tree, alertify, generateUrl, args) {
return setTriggers(tree, alertify, generateUrl, args, {enable: 'true' });
return setTriggers(tree, alertify, generateUrl, args, {is_enable_trigger: 'O' });
}
function setTriggers(tree, alertify, generateUrl, args, params) {

View File

@ -1,2 +1,3 @@
{% set enable_map = {'R':'ENABLE REPLICA', 'A':'ENABLE ALWAYS', 'O':'ENABLE', 'D':'DISABLE'} %}
ALTER TABLE {{ conn|qtIdent(data.schema, data.table) }}
{% if data.is_enable_trigger == True %}ENABLE{% else %}DISABLE{% endif %} TRIGGER {{ conn|qtIdent(data.name) }};
{{ enable_map[data.is_enable_trigger] }} TRIGGER {{ conn|qtIdent(data.name) }};

View File

@ -1,4 +1,4 @@
SELECT t.oid, t.tgname as name, (CASE WHEN tgenabled = 'O' THEN true ElSE false END) AS is_enable_trigger
SELECT t.oid, t.tgname as name, t.tgenabled AS is_enable_trigger
FROM pg_trigger t
WHERE NOT tgisinternal

View File

@ -1,4 +1,4 @@
SELECT t.oid,t.tgname AS name, t.xmin, t.tgtype, t.tgattr, relname,
SELECT t.oid,t.tgname AS name, t.xmin, t.tgenabled AS is_enable_trigger, t.tgtype, t.tgattr, relname,
CASE WHEN relkind = 'r' THEN TRUE ELSE FALSE END AS parentistable,
nspname, des.description,
regexp_replace(regexp_replace(pg_get_triggerdef(t.oid),
@ -6,9 +6,8 @@ SELECT t.oid,t.tgname AS name, t.xmin, t.tgtype, t.tgattr, relname,
) AS prosrc,
COALESCE(substring(pg_get_triggerdef(t.oid), 'WHEN (.*) \nCOMPOUND'), NULL) AS whenclause,
{% if datlastsysoid %}
(CASE WHEN t.oid <= {{ datlastsysoid}}::oid THEN true ElSE false END) AS is_sys_trigger,
(CASE WHEN t.oid <= {{ datlastsysoid}}::oid THEN true ElSE false END) AS is_sys_trigger
{% endif %}
(CASE WHEN tgenabled = 'O' THEN true ElSE false END) AS is_enable_trigger
FROM pg_trigger t
JOIN pg_class cl ON cl.oid=tgrelid
JOIN pg_namespace na ON na.oid=relnamespace

View File

@ -38,6 +38,7 @@ COMMENT ON TRIGGER {{ conn|qtIdent(data.name) }} ON {{ conn|qtIdent(o_data.nspna
IS {{data.description|qtLiteral}};
{% endif %}
{% if data.is_enable_trigger is defined and o_data.is_enable_trigger != data.is_enable_trigger %}
{% set enable_map = {'R':'ENABLE REPLICA', 'A':'ENABLE ALWAYS', 'O':'ENABLE', 'D':'DISABLE'} %}
ALTER TABLE {{ conn|qtIdent(o_data.nspname, o_data.relname) }}
{% if data.is_enable_trigger == True %}ENABLE{% else %}DISABLE{% endif %} TRIGGER {{ conn|qtIdent(data.name) }};
{{ enable_map[data.is_enable_trigger] }} TRIGGER {{ conn|qtIdent(data.name) }};
{% endif %}

View File

@ -1,2 +1,3 @@
{% set enable_map = {'O':'ENABLE', 'D':'DISABLE'} %}
ALTER TABLE {{ conn|qtIdent(data.schema, data.name) }}
{% if is_enable_trigger == True %}ENABLE{% else %}DISABLE{% endif %} TRIGGER ALL;
{{ enable_map[is_enable_trigger] }} TRIGGER ALL;

View File

@ -1,6 +1,5 @@
SELECT t.oid, t.tgname as name, (CASE WHEN tgenabled = 'O' THEN true ElSE false END) AS is_enable_trigger
SELECT t.oid, t.tgname as name, t.tgenabled AS is_enable_trigger
FROM pg_trigger t
WHERE NOT tgisinternal
AND tgrelid = {{tid}}::OID
{% if trid %}

View File

@ -1,4 +1,4 @@
SELECT t.oid,t.tgname AS name, t.xmin, t.*, relname, CASE WHEN relkind = 'r' THEN TRUE ELSE FALSE END AS parentistable,
SELECT t.oid,t.tgname AS name, t.xmin, t.tgenabled AS is_enable_trigger, t.*, relname, CASE WHEN relkind = 'r' THEN TRUE ELSE FALSE END AS parentistable,
nspname, des.description, l.lanname, p.prosrc, p.proname AS tfunction,
COALESCE(substring(pg_get_triggerdef(t.oid), 'WHEN (.*) EXECUTE PROCEDURE'),
substring(pg_get_triggerdef(t.oid), 'WHEN (.*) \$trigger')) AS whenclause,
@ -7,8 +7,7 @@ SELECT t.oid,t.tgname AS name, t.xmin, t.*, relname, CASE WHEN relkind = 'r' THE
{% if datlastsysoid %}
(CASE WHEN t.oid <= {{ datlastsysoid}}::oid THEN true ElSE false END) AS is_sys_trigger,
{% endif %}
(CASE WHEN tgconstraint != 0::OID THEN true ElSE false END) AS is_constraint_trigger,
(CASE WHEN tgenabled = 'O' THEN true ElSE false END) AS is_enable_trigger
(CASE WHEN tgconstraint != 0::OID THEN true ElSE false END) AS is_constraint_trigger
FROM pg_trigger t
JOIN pg_class cl ON cl.oid=tgrelid
JOIN pg_namespace na ON na.oid=relnamespace

View File

@ -1,2 +1,3 @@
{% set enable_map = {'R':'ENABLE REPLICA', 'A':'ENABLE ALWAYS', 'O':'ENABLE', 'D':'DISABLE'} %}
ALTER TABLE {{ conn|qtIdent(data.schema, data.table) }}
{% if data.is_enable_trigger == True %}ENABLE{% else %}DISABLE{% endif %} TRIGGER {{ conn|qtIdent(data.name) }};
{{ enable_map[data.is_enable_trigger] }} TRIGGER {{ conn|qtIdent(data.name) }};

View File

@ -1,4 +1,4 @@
SELECT t.oid, t.tgname as name, (CASE WHEN tgenabled = 'O' THEN true ElSE false END) AS is_enable_trigger
SELECT t.oid, t.tgname as name, t.tgenabled AS is_enable_trigger
FROM pg_trigger t
WHERE tgrelid = {{tid}}::OID
{% if trid %}

View File

@ -45,6 +45,7 @@ COMMENT ON TRIGGER {{ conn|qtIdent(data.name) }} ON {{ conn|qtIdent(o_data.nspna
IS {{data.description|qtLiteral}};
{% endif %}
{% if data.is_enable_trigger is defined and o_data.is_enable_trigger != data.is_enable_trigger %}
{% set enable_map = {'R':'ENABLE REPLICA', 'A':'ENABLE ALWAYS', 'O':'ENABLE', 'D':'DISABLE'} %}
ALTER TABLE {{ conn|qtIdent(o_data.nspname, o_data.relname) }}
{% if data.is_enable_trigger == True %}ENABLE{% else %}DISABLE{% endif %} TRIGGER {{ conn|qtIdent(data.name) }};
{{ enable_map[data.is_enable_trigger] }} TRIGGER {{ conn|qtIdent(data.name) }};
{% endif %}

View File

@ -1,4 +1,4 @@
SELECT t.oid,t.tgname AS name, t.xmin, t.*, relname, CASE WHEN relkind = 'r' THEN TRUE ELSE FALSE END AS parentistable,
SELECT t.oid,t.tgname AS name, t.xmin, t.tgenabled AS is_enable_trigger, t.*, relname, CASE WHEN relkind = 'r' THEN TRUE ELSE FALSE END AS parentistable,
nspname, des.description, l.lanname, p.prosrc, p.proname AS tfunction,
COALESCE(substring(pg_get_triggerdef(t.oid), 'WHEN (.*) EXECUTE PROCEDURE'),
substring(pg_get_triggerdef(t.oid), 'WHEN (.*) \$trigger')) AS whenclause,
@ -8,7 +8,6 @@ SELECT t.oid,t.tgname AS name, t.xmin, t.*, relname, CASE WHEN relkind = 'r' THE
(CASE WHEN t.oid <= {{ datlastsysoid}}::oid THEN true ElSE false END) AS is_sys_trigger,
{% endif %}
(CASE WHEN tgconstraint != 0::OID THEN true ElSE false END) AS is_constraint_trigger,
(CASE WHEN tgenabled = 'O' THEN true ElSE false END) AS is_enable_trigger,
tgoldtable,
tgnewtable
FROM pg_trigger t

View File

@ -1,6 +1,5 @@
SELECT t.oid, t.tgname as name, (CASE WHEN tgenabled = 'O' THEN true ElSE false END) AS is_enable_trigger
SELECT t.oid, t.tgname as name, t.tgenabled AS is_enable_trigger
FROM pg_trigger t
WHERE NOT tgisinternal
AND tgrelid = {{tid}}::OID
{% if trid %}

View File

@ -1,4 +1,4 @@
SELECT t.oid,t.tgname AS name, t.xmin, t.*, relname, CASE WHEN relkind = 'r' THEN TRUE ELSE FALSE END AS parentistable,
SELECT t.oid,t.tgname AS name, t.xmin, t.tgenabled AS is_enable_trigger, t.*, relname, CASE WHEN relkind = 'r' THEN TRUE ELSE FALSE END AS parentistable,
nspname, des.description, l.lanname, p.prosrc, p.proname AS tfunction,
COALESCE(substring(pg_get_triggerdef(t.oid), 'WHEN (.*) EXECUTE PROCEDURE'),
substring(pg_get_triggerdef(t.oid), 'WHEN (.*) \$trigger')) AS whenclause,
@ -7,8 +7,7 @@ SELECT t.oid,t.tgname AS name, t.xmin, t.*, relname, CASE WHEN relkind = 'r' THE
{% if datlastsysoid %}
(CASE WHEN t.oid <= {{ datlastsysoid}}::oid THEN true ElSE false END) AS is_sys_trigger,
{% endif %}
(CASE WHEN tgconstraint != 0::OID THEN true ElSE false END) AS is_constraint_trigger,
(CASE WHEN tgenabled = 'O' THEN true ElSE false END) AS is_enable_trigger
(CASE WHEN tgconstraint != 0::OID THEN true ElSE false END) AS is_constraint_trigger
FROM pg_trigger t
JOIN pg_class cl ON cl.oid=tgrelid
JOIN pg_namespace na ON na.oid=relnamespace

View File

@ -1,2 +1,3 @@
{% set enable_map = {'R':'ENABLE REPLICA', 'A':'ENABLE ALWAYS', 'O':'ENABLE', 'D':'DISABLE'} %}
ALTER TABLE {{ conn|qtIdent(data.schema, data.table) }}
{% if data.is_enable_trigger == True %}ENABLE{% else %}DISABLE{% endif %} TRIGGER {{ conn|qtIdent(data.name) }};
{{ enable_map[data.is_enable_trigger] }} TRIGGER {{ conn|qtIdent(data.name) }};

View File

@ -1,4 +1,4 @@
SELECT t.oid, t.tgname as name, (CASE WHEN tgenabled = 'O' THEN true ElSE false END) AS is_enable_trigger
SELECT t.oid, t.tgname as name, t.tgenabled AS is_enable_trigger
FROM pg_trigger t
WHERE tgrelid = {{tid}}::OID
{% if trid %}

View File

@ -45,6 +45,7 @@ COMMENT ON TRIGGER {{ conn|qtIdent(data.name) }} ON {{ conn|qtIdent(o_data.nspna
IS {{data.description|qtLiteral}};
{% endif %}
{% if data.is_enable_trigger is defined and o_data.is_enable_trigger != data.is_enable_trigger %}
{% set enable_map = {'R':'ENABLE REPLICA', 'A':'ENABLE ALWAYS', 'O':'ENABLE', 'D':'DISABLE'} %}
ALTER TABLE {{ conn|qtIdent(o_data.nspname, o_data.relname) }}
{% if data.is_enable_trigger == True %}ENABLE{% else %}DISABLE{% endif %} TRIGGER {{ conn|qtIdent(data.name) }};
{{ enable_map[data.is_enable_trigger] }} TRIGGER {{ conn|qtIdent(data.name) }};
{% endif %}

View File

@ -1,4 +1,4 @@
SELECT t.oid,t.tgname AS name, t.xmin, t.*, relname, CASE WHEN relkind = 'r' THEN TRUE ELSE FALSE END AS parentistable,
SELECT t.oid,t.tgname AS name, t.xmin, t.tgenabled AS is_enable_trigger, t.*, relname, CASE WHEN relkind = 'r' THEN TRUE ELSE FALSE END AS parentistable,
nspname, des.description, l.lanname, p.prosrc, p.proname AS tfunction,
COALESCE(substring(pg_get_triggerdef(t.oid), 'WHEN (.*) EXECUTE PROCEDURE'),
substring(pg_get_triggerdef(t.oid), 'WHEN (.*) \$trigger')) AS whenclause,
@ -8,7 +8,6 @@ SELECT t.oid,t.tgname AS name, t.xmin, t.*, relname, CASE WHEN relkind = 'r' THE
(CASE WHEN t.oid <= {{ datlastsysoid}}::oid THEN true ElSE false END) AS is_sys_trigger,
{% endif %}
(CASE WHEN tgconstraint != 0::OID THEN true ElSE false END) AS is_constraint_trigger,
(CASE WHEN tgenabled = 'O' THEN true ElSE false END) AS is_enable_trigger,
tgoldtable,
tgnewtable
FROM pg_trigger t

View File

@ -1,6 +1,5 @@
SELECT t.oid, t.tgname as name, (CASE WHEN tgenabled = 'O' THEN true ElSE false END) AS is_enable_trigger
SELECT t.oid, t.tgname as name, t.tgenabled AS is_enable_trigger
FROM pg_trigger t
WHERE NOT tgisinternal
AND tgrelid = {{tid}}::OID
AND tgpackageoid = 0

View File

@ -1,4 +1,4 @@
SELECT t.oid,t.tgname AS name, t.xmin, t.*, relname, CASE WHEN relkind = 'r' THEN TRUE ELSE FALSE END AS parentistable,
SELECT t.oid,t.tgname AS name, t.xmin, t.tgenabled AS is_enable_trigger, t.*, relname, CASE WHEN relkind = 'r' THEN TRUE ELSE FALSE END AS parentistable,
nspname, des.description, l.lanname, p.prosrc, p.proname AS tfunction,
COALESCE(substring(pg_get_triggerdef(t.oid), 'WHEN (.*) EXECUTE PROCEDURE'),
substring(pg_get_triggerdef(t.oid), 'WHEN (.*) \$trigger')) AS whenclause,
@ -8,7 +8,6 @@ SELECT t.oid,t.tgname AS name, t.xmin, t.*, relname, CASE WHEN relkind = 'r' THE
(CASE WHEN t.oid <= {{ datlastsysoid}}::oid THEN true ElSE false END) AS is_sys_trigger,
{% endif %}
(CASE WHEN tgconstraint != 0::OID THEN true ElSE false END) AS is_constraint_trigger,
(CASE WHEN tgenabled = 'O' THEN true ElSE false END) AS is_enable_trigger,
tgoldtable,
tgnewtable
FROM pg_trigger t

View File

@ -1,6 +1,5 @@
SELECT t.oid, t.tgname as name, (CASE WHEN tgenabled = 'O' THEN true ElSE false END) AS is_enable_trigger
SELECT t.oid, t.tgname as name, t.tgenabled AS is_enable_trigger
FROM pg_trigger t
WHERE NOT tgisinternal
AND tgrelid = {{tid}}::OID
{% if trid %}

View File

@ -1,4 +1,4 @@
SELECT t.oid,t.tgname AS name, t.xmin, t.*, relname, CASE WHEN relkind = 'r' THEN TRUE ELSE FALSE END AS parentistable,
SELECT t.oid,t.tgname AS name, t.xmin, t.tgenabled AS is_enable_trigger, t.*, relname, CASE WHEN relkind = 'r' THEN TRUE ELSE FALSE END AS parentistable,
nspname, des.description, l.lanname, p.prosrc, p.proname AS tfunction,
COALESCE(substring(pg_get_triggerdef(t.oid), 'WHEN (.*) EXECUTE PROCEDURE'),
substring(pg_get_triggerdef(t.oid), 'WHEN (.*) \$trigger')) AS whenclause,
@ -7,8 +7,7 @@ SELECT t.oid,t.tgname AS name, t.xmin, t.*, relname, CASE WHEN relkind = 'r' THE
{% if datlastsysoid %}
(CASE WHEN t.oid <= {{ datlastsysoid}}::oid THEN true ElSE false END) AS is_sys_trigger,
{% endif %}
(CASE WHEN tgconstraint != 0::OID THEN true ElSE false END) AS is_constraint_trigger,
(CASE WHEN tgenabled = 'O' THEN true ElSE false END) AS is_enable_trigger
(CASE WHEN tgconstraint != 0::OID THEN true ElSE false END) AS is_constraint_trigger
FROM pg_trigger t
JOIN pg_class cl ON cl.oid=tgrelid
JOIN pg_namespace na ON na.oid=relnamespace

View File

@ -1,2 +1,3 @@
{% set enable_map = {'R':'ENABLE REPLICA', 'A':'ENABLE ALWAYS', 'O':'ENABLE', 'D':'DISABLE'} %}
ALTER TABLE {{ conn|qtIdent(data.schema, data.table) }}
{% if data.is_enable_trigger == True %}ENABLE{% else %}DISABLE{% endif %} TRIGGER {{ conn|qtIdent(data.name) }};
{{ enable_map[data.is_enable_trigger] }} TRIGGER {{ conn|qtIdent(data.name) }};

View File

@ -1,4 +1,4 @@
SELECT t.oid, t.tgname as name, (CASE WHEN tgenabled = 'O' THEN true ElSE false END) AS is_enable_trigger
SELECT t.oid, t.tgname as name, t.tgenabled AS is_enable_trigger
FROM pg_trigger t
WHERE tgrelid = {{tid}}::OID
{% if trid %}

View File

@ -45,6 +45,7 @@ COMMENT ON TRIGGER {{ conn|qtIdent(data.name) }} ON {{ conn|qtIdent(o_data.nspna
IS {{data.description|qtLiteral}};
{% endif %}
{% if data.is_enable_trigger is defined and o_data.is_enable_trigger != data.is_enable_trigger %}
{% set enable_map = {'R':'ENABLE REPLICA', 'A':'ENABLE ALWAYS', 'O':'ENABLE', 'D':'DISABLE'} %}
ALTER TABLE {{ conn|qtIdent(o_data.nspname, o_data.relname) }}
{% if data.is_enable_trigger == True %}ENABLE{% else %}DISABLE{% endif %} TRIGGER {{ conn|qtIdent(data.name) }};
{{ enable_map[data.is_enable_trigger] }} TRIGGER {{ conn|qtIdent(data.name) }};
{% endif %}

View File

@ -410,8 +410,8 @@ class TriggerView(PGChildNodeView):
rset['rows'][0]['oid'],
tid,
rset['rows'][0]['name'],
icon="icon-trigger" if
rset['rows'][0]['is_enable_trigger'] else "icon-trigger-bad"
icon="icon-trigger-bad" if
rset['rows'][0]['is_enable_trigger'] == 'D' else "icon-trigger"
)
return make_json_response(
@ -449,8 +449,8 @@ class TriggerView(PGChildNodeView):
row['oid'],
tid,
row['name'],
icon="icon-trigger" if row['is_enable_trigger']
else "icon-trigger-bad"
icon="icon-trigger-bad" if row['is_enable_trigger'] == 'D'
else "icon-trigger"
))
return make_json_response(
@ -804,9 +804,9 @@ class TriggerView(PGChildNodeView):
new_trid,
tid,
name,
icon="icon-%s" % self.node_type if
data['is_enable_trigger'] else
"icon-%s-bad" % self.node_type
icon="icon-%s-bad" % self.node_type if
data['is_enable_trigger'] == 'D' else
"icon-%s" % self.node_type
)
)
except Exception as e:
@ -999,7 +999,7 @@ class TriggerView(PGChildNodeView):
SQL = sql_header + '\n\n' + SQL.strip('\n')
# If trigger is disbaled then add sql code for the same
if not data['is_enable_trigger']:
if data['is_enable_trigger'] != 'O':
SQL += '\n\n'
SQL += render_template("/".join([self.template_path,
'enable_disable_trigger.sql']),
@ -1025,8 +1025,7 @@ class TriggerView(PGChildNodeView):
request.data, encoding='utf-8'
)
# Convert str 'true' to boolean type
is_enable_flag = json.loads(data['enable'])
is_enable_trigger = data['is_enable_trigger']
try:
@ -1049,7 +1048,7 @@ class TriggerView(PGChildNodeView):
# current trigger which is disabled already so we need to
# alter the 'is_enable_trigger' flag so that we can render
# correct SQL for operation
o_data['is_enable_trigger'] = is_enable_flag
o_data['is_enable_trigger'] = is_enable_trigger
# Adding parent into data dict, will be using it while creating sql
o_data['schema'] = self.schema

View File

@ -108,7 +108,7 @@ define('pgadmin.node.trigger', [
$.ajax({
url: obj.generate_url(i, 'enable' , d, true),
type:'PUT',
data: {'enable' : true},
data: {'is_enable_trigger' : 'O'},
dataType: 'json',
})
.done(function(res) {
@ -146,7 +146,7 @@ define('pgadmin.node.trigger', [
$.ajax({
url: obj.generate_url(i, 'enable' , d, true),
type:'PUT',
data: {'enable' : false},
data: {'is_enable_trigger' : 'D'},
dataType: 'json',
})
.done(function(res) {
@ -187,13 +187,20 @@ define('pgadmin.node.trigger', [
type: 'int', disabled: true, mode: ['properties'],
},{
id: 'is_enable_trigger', label: gettext('Trigger enabled?'),
type: 'switch', mode: ['edit', 'properties'], group: gettext('Definition'),
mode: ['edit', 'properties'], group: gettext('Definition'),
disabled: function() {
if(this.node_info && ('catalog' in this.node_info || 'view' in this.node_info)) {
return true;
}
return false;
},
options: [
{label: 'Enable', value: 'O'},
{label: 'Enable Replica', value: 'R'},
{label: 'Enable Always', value: 'A'},
{label: 'Disable', value: 'D'},
],
control: 'select2', select2: { allowClear: false, width: '100%' },
},{
id: 'is_row_trigger', label: gettext('Row trigger?'),
type: 'switch', group: gettext('Definition'),
@ -352,7 +359,6 @@ define('pgadmin.node.trigger', [
return view_options;
}
},
// If create mode then by default open composite type
control: 'select2', select2: { allowClear: false, width: '100%' },
disabled: function(m) {
// If contraint trigger is set to True then only enable it

View File

@ -28,7 +28,18 @@ class TriggersUpdateTestCase(BaseTestGenerator):
"""This class will update trigger under table node."""
skip_on_database = ['gpdb']
scenarios = [
('Put trigger Node URL', dict(url='/browser/trigger/obj/'))
('Put trigger Node URL', dict(
url='/browser/trigger/obj/',
data={"description": "This is test comment."})),
('Enable Always compound trigger',
dict(url='/browser/trigger/obj/',
data={"is_enable_trigger": 'A'})),
('Enable Replica compound trigger',
dict(url='/browser/trigger/obj/',
data={"is_enable_trigger": 'R'})),
('Disable compound trigger',
dict(url='/browser/trigger/obj/',
data={"is_enable_trigger": 'D'})),
]
def setUp(self):
@ -72,15 +83,14 @@ class TriggersUpdateTestCase(BaseTestGenerator):
self.trigger_name)
if not trigger_response:
raise Exception("Could not find the trigger to update.")
data = {"id": self.trigger_id,
"description": "This is test comment."
}
self.data.update({"id": self.trigger_id})
response = self.tester.put(
"{0}{1}/{2}/{3}/{4}/{5}/{6}".format(self.url, utils.SERVER_GROUP,
self.server_id, self.db_id,
self.schema_id, self.table_id,
self.trigger_id),
data=json.dumps(data),
data=json.dumps(self.data),
follow_redirects=True
)
self.assertEquals(response.status_code, 200)

View File

@ -1075,7 +1075,7 @@ class BaseTableView(PGChildNodeView, BasePartitionTable):
trigger_sql = sql_header + '\n\n' + trigger_sql.strip('\n')
# If trigger is disabled then add sql code for the same
if not data['is_enable_trigger']:
if data['is_enable_trigger'] != 'O':
trigger_sql += '\n\n'
trigger_sql += render_template("/".join([
self.trigger_template_path,
@ -1155,7 +1155,7 @@ class BaseTableView(PGChildNodeView, BasePartitionTable):
sql_header + '\n\n' + compound_trigger_sql.strip('\n')
# If trigger is disabled then add sql code for the same
if not data['is_enable_trigger']:
if data['is_enable_trigger'] != 'O':
compound_trigger_sql += '\n\n'
compound_trigger_sql += render_template("/".join(
[self.compound_trigger_template_path,

View File

@ -106,7 +106,7 @@ describe('#enableTriggers', () => {
it('call backend with the correct parameters', (done) => {
enableTriggers(tree, alertify, generateUrlSpy, {item: [{id: 'table1'}]});
setTimeout(() => {
expect(networkMockCalledWith.data).toEqual(JSON.stringify({enable: 'true'}));
expect(networkMockCalledWith.data).toEqual(JSON.stringify({is_enable_trigger: 'O'}));
done();
}, 0);
});
@ -234,7 +234,7 @@ describe('#disableTriggers', () => {
it('call backend with the correct parameters', (done) => {
disableTriggers(tree, alertify, generateUrlSpy, {item: [{id: 'table1'}]});
setTimeout(() => {
expect(networkMockCalledWith.data).toEqual(JSON.stringify({enable: 'false'}));
expect(networkMockCalledWith.data).toEqual(JSON.stringify({is_enable_trigger: 'D'}));
done();
}, 0);
});