i_tgconstrrelid,
i_tgconstrrelname,
i_tgenabled,
+ i_tgisinternal,
i_tgdeferrable,
i_tginitdeferred,
i_tgdef;
tbinfo->dobj.name);
resetPQExpBuffer(query);
- if (fout->remoteVersion >= 90000)
+ if (fout->remoteVersion >= 130000)
{
/*
* NB: think not to use pretty=true in pg_get_triggerdef. It
* could result in non-forward-compatible dumps of WHEN clauses
* due to under-parenthesization.
+ *
+ * NB: We need to see tgisinternal triggers in partitions, in case
+ * the tgenabled flag has been changed from the parent.
*/
appendPQExpBuffer(query,
- "SELECT tgname, "
- "tgfoid::pg_catalog.regproc AS tgfname, "
- "pg_catalog.pg_get_triggerdef(oid, false) AS tgdef, "
- "tgenabled, tableoid, oid "
+ "SELECT t.tgname, "
+ "t.tgfoid::pg_catalog.regproc AS tgfname, "
+ "pg_catalog.pg_get_triggerdef(t.oid, false) AS tgdef, "
+ "t.tgenabled, t.tableoid, t.oid, t.tgisinternal "
+ "FROM pg_catalog.pg_trigger t "
+ "LEFT JOIN pg_catalog.pg_trigger u ON u.oid = t.tgparentid "
+ "WHERE t.tgrelid = '%u'::pg_catalog.oid "
+ "AND (NOT t.tgisinternal OR t.tgenabled != u.tgenabled)",
+ tbinfo->dobj.catId.oid);
+ }
+ else if (fout->remoteVersion >= 110000)
+ {
+ /*
+ * NB: We need to see tgisinternal triggers in partitions, in case
+ * the tgenabled flag has been changed from the parent. No
+ * tgparentid in version 11-12, so we have to match them via
+ * pg_depend.
+ *
+ * See above about pretty=true in pg_get_triggerdef.
+ */
+ appendPQExpBuffer(query,
+ "SELECT t.tgname, "
+ "t.tgfoid::pg_catalog.regproc AS tgfname, "
+ "pg_catalog.pg_get_triggerdef(t.oid, false) AS tgdef, "
+ "t.tgenabled, t.tableoid, t.oid, t.tgisinternal "
+ "FROM pg_catalog.pg_trigger t "
+ "LEFT JOIN pg_catalog.pg_depend AS d ON "
+ " d.classid = 'pg_catalog.pg_trigger'::pg_catalog.regclass AND "
+ " d.refclassid = 'pg_catalog.pg_trigger'::pg_catalog.regclass AND "
+ " d.objid = t.oid "
+ "LEFT JOIN pg_catalog.pg_trigger AS pt ON pt.oid = refobjid "
+ "WHERE t.tgrelid = '%u'::pg_catalog.oid "
+ "AND (NOT t.tgisinternal%s)",
+ tbinfo->dobj.catId.oid,
+ tbinfo->ispartition ?
+ " OR t.tgenabled != pt.tgenabled" : "");
+ }
+ else if (fout->remoteVersion >= 90000)
+ {
+ /* See above about pretty=true in pg_get_triggerdef */
+ appendPQExpBuffer(query,
+ "SELECT t.tgname, "
+ "t.tgfoid::pg_catalog.regproc AS tgfname, "
+ "pg_catalog.pg_get_triggerdef(t.oid, false) AS tgdef, "
+ "t.tgenabled, false as tgisinternal, "
+ "t.tableoid, t.oid "
"FROM pg_catalog.pg_trigger t "
"WHERE tgrelid = '%u'::pg_catalog.oid "
"AND NOT tgisinternal",
"SELECT tgname, "
"tgfoid::pg_catalog.regproc AS tgfname, "
"tgtype, tgnargs, tgargs, tgenabled, "
+ "false as tgisinternal, "
"tgisconstraint, tgconstrname, tgdeferrable, "
"tgconstrrelid, tginitdeferred, tableoid, oid, "
"tgconstrrelid::pg_catalog.regclass AS tgconstrrelname "
i_tgconstrrelid = PQfnumber(res, "tgconstrrelid");
i_tgconstrrelname = PQfnumber(res, "tgconstrrelname");
i_tgenabled = PQfnumber(res, "tgenabled");
+ i_tgisinternal = PQfnumber(res, "tgisinternal");
i_tgdeferrable = PQfnumber(res, "tgdeferrable");
i_tginitdeferred = PQfnumber(res, "tginitdeferred");
i_tgdef = PQfnumber(res, "tgdef");
tginfo[j].dobj.namespace = tbinfo->dobj.namespace;
tginfo[j].tgtable = tbinfo;
tginfo[j].tgenabled = *(PQgetvalue(res, j, i_tgenabled));
+ tginfo[j].tgisinternal = *(PQgetvalue(res, j, i_tgisinternal)) == 't';
if (i_tgdef >= 0)
{
tginfo[j].tgdef = pg_strdup(PQgetvalue(res, j, i_tgdef));
"pg_catalog.pg_trigger", "TRIGGER",
trigidentity->data);
- if (tginfo->tgenabled != 't' && tginfo->tgenabled != 'O')
+ if (tginfo->tgisinternal)
+ {
+ /*
+ * Triggers marked internal only appear here because their 'tgenabled'
+ * flag differs from its parent's. The trigger is created already, so
+ * remove the CREATE and replace it with an ALTER. (Clear out the
+ * DROP query too, so that pg_dump --create does not cause errors.)
+ */
+ resetPQExpBuffer(query);
+ resetPQExpBuffer(delqry);
+ appendPQExpBuffer(query, "\nALTER %sTABLE %s ",
+ tbinfo->relkind == RELKIND_FOREIGN_TABLE ? "FOREIGN " : "",
+ fmtQualifiedDumpable(tbinfo));
+ switch (tginfo->tgenabled)
+ {
+ case 'f':
+ case 'D':
+ appendPQExpBufferStr(query, "DISABLE");
+ break;
+ case 't':
+ case 'O':
+ appendPQExpBufferStr(query, "ENABLE");
+ break;
+ case 'R':
+ appendPQExpBufferStr(query, "ENABLE REPLICA");
+ break;
+ case 'A':
+ appendPQExpBufferStr(query, "ENABLE ALWAYS");
+ break;
+ }
+ appendPQExpBuffer(query, " TRIGGER %s;\n",
+ fmtId(tginfo->dobj.name));
+ }
+ else if (tginfo->tgenabled != 't' && tginfo->tgenabled != 'O')
{
appendPQExpBuffer(query, "\nALTER %sTABLE %s ",
tbinfo->relkind == RELKIND_FOREIGN_TABLE ? "FOREIGN " : "",
},
},
- # this shouldn't ever get emitted
- 'Creation of row-level trigger in partition' => {
+ 'Disabled trigger on partition is altered' => {
+ create_order => 93,
+ create_sql =>
+ 'CREATE TABLE dump_test_second_schema.measurement_y2006m3
+ PARTITION OF dump_test.measurement
+ FOR VALUES FROM (\'2006-03-01\') TO (\'2006-04-01\');
+ ALTER TABLE dump_test_second_schema.measurement_y2006m3 DISABLE TRIGGER test_trigger;
+ CREATE TABLE dump_test_second_schema.measurement_y2006m4
+ PARTITION OF dump_test.measurement
+ FOR VALUES FROM (\'2006-04-01\') TO (\'2006-05-01\');
+ ALTER TABLE dump_test_second_schema.measurement_y2006m4 ENABLE REPLICA TRIGGER test_trigger;
+ CREATE TABLE dump_test_second_schema.measurement_y2006m5
+ PARTITION OF dump_test.measurement
+ FOR VALUES FROM (\'2006-05-01\') TO (\'2006-06-01\');
+ ALTER TABLE dump_test_second_schema.measurement_y2006m5 ENABLE ALWAYS TRIGGER test_trigger;
+ ',
+ regexp => qr/^
+ \QALTER TABLE dump_test_second_schema.measurement_y2006m3 DISABLE TRIGGER test_trigger;\E
+ /xm,
+ like => {
+ %full_runs,
+ section_post_data => 1,
+ role => 1,
+ binary_upgrade => 1,
+ },
+ },
+
+ 'Replica trigger on partition is altered' => {
regexp => qr/^
- \QCREATE TRIGGER test_trigger AFTER INSERT ON dump_test_second_schema.measurement\E
+ \QALTER TABLE dump_test_second_schema.measurement_y2006m4 ENABLE REPLICA TRIGGER test_trigger;\E
/xm,
- like => {},
+ like => {
+ %full_runs,
+ section_post_data => 1,
+ role => 1,
+ binary_upgrade => 1,
+ },
+ },
+
+ 'Always trigger on partition is altered' => {
+ regexp => qr/^
+ \QALTER TABLE dump_test_second_schema.measurement_y2006m5 ENABLE ALWAYS TRIGGER test_trigger;\E
+ /xm,
+ like => {
+ %full_runs,
+ section_post_data => 1,
+ role => 1,
+ binary_upgrade => 1,
+ },
+ },
+
+ # We should never see the creation of a trigger on a partition
+ 'Disabled trigger on partition is not created' => {
+ regexp => qr/CREATE TRIGGER test_trigger.*ON dump_test_second_schema/,
+ like => {},
+ unlike => { %full_runs, %dump_test_schema_runs },
+ },
+
+ # Triggers on partitions should not be dropped individually
+ 'Triggers on partitions are not dropped' => {
+ regexp => qr/DROP TRIGGER test_trigger.*ON dump_test_second_schema/,
+ like => {}
},
'CREATE TABLE test_fourth_table_zero_col' => {
},
'GRANT SELECT ON TABLE measurement_y2006m2' => {
- create_order => 92,
- create_sql => 'GRANT SELECT ON
- TABLE dump_test_second_schema.measurement_y2006m2
+ create_order => 94,
+ create_sql => 'GRANT SELECT ON TABLE
+ dump_test_second_schema.measurement_y2006m2,
+ dump_test_second_schema.measurement_y2006m3,
+ dump_test_second_schema.measurement_y2006m4,
+ dump_test_second_schema.measurement_y2006m5
TO regress_dump_test_role;',
regexp =>
qr/^\QGRANT SELECT ON TABLE dump_test_second_schema.measurement_y2006m2 TO regress_dump_test_role;\E/m,