Skip to content

Commit ecec006

Browse files
committed
auto trigger creation for partitions
1 parent e0d3fe0 commit ecec006

File tree

7 files changed

+175
-96
lines changed

7 files changed

+175
-96
lines changed

expected/pathman_basic.out

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1321,6 +1321,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE dt BETWEEN '2014-11-15' A
13211321
(6 rows)
13221322

13231323
SELECT pathman.detach_range_partition('test.range_rel_archive');
1324+
NOTICE: trigger "range_rel_upd_trig" for relation "test.range_rel_archive" does not exist, skipping
13241325
detach_range_partition
13251326
------------------------
13261327
test.range_rel_archive
@@ -1734,6 +1735,7 @@ SELECT * FROM test."TeSt";
17341735
1 | 1
17351736
(3 rows)
17361737

1738+
DROP TABLE test."TeSt" CASCADE;
17371739
CREATE TABLE test."RangeRel" (
17381740
id SERIAL PRIMARY KEY,
17391741
dt TIMESTAMP NOT NULL,
@@ -2189,6 +2191,6 @@ ORDER BY partition;
21892191
DROP TABLE test.provided_part_names CASCADE;
21902192
NOTICE: drop cascades to 2 other objects
21912193
DROP SCHEMA test CASCADE;
2192-
NOTICE: drop cascades to 49 other objects
2194+
NOTICE: drop cascades to 48 other objects
21932195
DROP EXTENSION pg_pathman CASCADE;
21942196
DROP SCHEMA pathman CASCADE;

init.sql

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,17 @@ LANGUAGE C;
562562
*/
563563
CREATE OR REPLACE FUNCTION @extschema@.create_update_triggers(parent_relid REGCLASS)
564564
RETURNS VOID AS 'pg_pathman', 'create_update_triggers'
565-
LANGUAGE C;
565+
LANGUAGE C STRICT;
566+
567+
CREATE OR REPLACE FUNCTION @extschema@.create_single_update_trigger(
568+
parent_relid REGCLASS,
569+
partition_relid REGCLASS)
570+
RETURNS VOID AS 'pg_pathman', 'create_single_update_trigger'
571+
LANGUAGE C STRICT;
572+
573+
CREATE OR REPLACE FUNCTION @extschema@.is_update_trigger_enabled(parent_relid REGCLASS)
574+
RETURNS BOOL AS 'pg_pathman', 'is_update_trigger_enabled'
575+
LANGUAGE C STRICT;
566576

567577
/*
568578
* Drop triggers
@@ -580,13 +590,22 @@ BEGIN
580590

581591
/* Drop trigger for each partition if exists */
582592
FOR rec IN (SELECT pg_catalog.pg_inherits.* FROM pg_catalog.pg_inherits
583-
JOIN pg_catalog.pg_trigger on inhrelid = tgrelid
593+
JOIN pg_catalog.pg_trigger ON inhrelid = tgrelid
584594
WHERE inhparent = parent_relid AND tgname = triggername)
585595
LOOP
586596
EXECUTE format('DROP TRIGGER IF EXISTS %s ON %s',
587597
triggername,
588598
rec.inhrelid::REGCLASS::TEXT);
589599
END LOOP;
600+
601+
/* Drop trigger on parent */
602+
IF EXISTS (SELECT * FROM pg_catalog.pg_trigger
603+
WHERE tgname = triggername AND tgrelid = parent_relid)
604+
THEN
605+
EXECUTE format('DROP TRIGGER IF EXISTS %s ON %s',
606+
triggername,
607+
parent_relid::TEXT);
608+
END IF;
590609
END
591610
$$ LANGUAGE plpgsql STRICT;
592611

range.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,12 @@ BEGIN
935935
ON params.partrel = parent_relid
936936
INTO v_init_callback;
937937

938+
/* If update trigger is enabled then create one for this partition */
939+
if @extschema@.is_update_trigger_enabled(parent_relid) THEN
940+
PERFORM @extschema@.create_single_update_trigger(parent_relid, partition_relid);
941+
END IF;
942+
943+
/* Invoke an initialization callback */
938944
PERFORM @extschema@.invoke_on_partition_created_callback(parent_relid,
939945
partition_relid,
940946
v_init_callback,
@@ -984,6 +990,11 @@ BEGIN
984990
partition_relid::TEXT,
985991
@extschema@.build_check_constraint_name(partition_relid, v_attname));
986992

993+
/* Remove update trigger */
994+
EXECUTE format('DROP TRIGGER IF EXISTS %s ON %s',
995+
@extschema@.build_update_trigger_name(parent_relid),
996+
partition_relid::TEXT);
997+
987998
/* Invalidate cache */
988999
PERFORM @extschema@.on_update_partitions(parent_relid);
9891000

sql/pathman_basic.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ SELECT * FROM test."TeSt" WHERE a = 1;
471471
EXPLAIN (COSTS OFF) SELECT * FROM test."TeSt" WHERE a = 1;
472472
SELECT pathman.drop_partitions('test."TeSt"');
473473
SELECT * FROM test."TeSt";
474+
DROP TABLE test."TeSt" CASCADE;
474475

475476
CREATE TABLE test."RangeRel" (
476477
id SERIAL PRIMARY KEY,

src/partition_creation.c

Lines changed: 114 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@
2222
#include "catalog/heap.h"
2323
#include "catalog/pg_authid.h"
2424
#include "catalog/pg_proc.h"
25+
#include "catalog/pg_trigger.h"
2526
#include "catalog/pg_type.h"
2627
#include "catalog/toasting.h"
2728
#include "commands/event_trigger.h"
2829
#include "commands/sequence.h"
2930
#include "commands/tablecmds.h"
3031
#include "commands/tablespace.h"
32+
#include "commands/trigger.h"
3133
#include "miscadmin.h"
3234
#include "parser/parse_func.h"
3335
#include "parser/parse_relation.h"
@@ -52,9 +54,11 @@ static Oid spawn_partitions_val(Oid parent_relid,
5254
Datum value,
5355
Oid value_type);
5456

55-
static void create_single_partition_common(Oid partition_relid,
57+
static void create_single_partition_common(Oid parent_relid,
58+
Oid partition_relid,
5659
Constraint *check_constraint,
57-
init_callback_params *callback_params);
60+
init_callback_params *callback_params,
61+
const char *attname);
5862

5963
static Oid create_single_partition_internal(Oid parent_relid,
6064
RangeVar *partition_rv,
@@ -77,6 +81,8 @@ static Constraint *make_constraint_common(char *name, Node *raw_expr);
7781
static Value make_string_value_struct(char *str);
7882
static Value make_int_value_struct(int int_val);
7983

84+
static bool update_trigger_exists(Oid relid, char *trigname);
85+
8086

8187
/*
8288
* ---------------------------------------
@@ -130,9 +136,11 @@ create_single_range_partition_internal(Oid parent_relid,
130136
*start_value, *end_value, value_type);
131137

132138
/* Add constraint & execute init_callback */
133-
create_single_partition_common(partition_relid,
139+
create_single_partition_common(parent_relid,
140+
partition_relid,
134141
check_constr,
135-
&callback_params);
142+
&callback_params,
143+
partitioned_column);
136144

137145
/* Return the Oid */
138146
return partition_relid;
@@ -183,21 +191,25 @@ create_single_hash_partition_internal(Oid parent_relid,
183191
parent_relid, partition_relid);
184192

185193
/* Add constraint & execute init_callback */
186-
create_single_partition_common(partition_relid,
194+
create_single_partition_common(parent_relid,
195+
partition_relid,
187196
check_constr,
188-
&callback_params);
197+
&callback_params,
198+
partitioned_column);
189199

190200
/* Return the Oid */
191201
return partition_relid;
192202
}
193203

194204
/* Add constraint & execute init_callback */
195205
void
196-
create_single_partition_common(Oid partition_relid,
206+
create_single_partition_common(Oid parent_relid,
207+
Oid partition_relid,
197208
Constraint *check_constraint,
198-
init_callback_params *callback_params)
209+
init_callback_params *callback_params,
210+
const char *attname)
199211
{
200-
Relation child_relation;
212+
Relation child_relation;
201213

202214
/* Open the relation and add new check constraint & fkeys */
203215
child_relation = heap_open(partition_relid, AccessExclusiveLock);
@@ -209,6 +221,20 @@ create_single_partition_common(Oid partition_relid,
209221
/* Make constraint visible */
210222
CommandCounterIncrement();
211223

224+
/* Create trigger */
225+
if (is_update_trigger_enabled_internal(parent_relid))
226+
{
227+
char *trigname;
228+
229+
trigname = build_update_trigger_name_internal(parent_relid);
230+
create_single_update_trigger_internal(partition_relid,
231+
trigname,
232+
attname);
233+
}
234+
235+
/* Make trigger visible */
236+
CommandCounterIncrement();
237+
212238
/* Finally invoke 'init_callback' */
213239
invoke_part_callback(callback_params);
214240

@@ -1649,3 +1675,82 @@ text_to_regprocedure(text *proc_signature)
16491675

16501676
return DatumGetObjectId(result);
16511677
}
1678+
1679+
/*
1680+
* Create trigger for partition
1681+
*/
1682+
void
1683+
create_single_update_trigger_internal(Oid relid,
1684+
const char *trigname,
1685+
const char *attname)
1686+
{
1687+
CreateTrigStmt *stmt;
1688+
List *func;
1689+
1690+
func = list_make2(makeString(get_namespace_name(get_pathman_schema())),
1691+
makeString("update_trigger_func"));
1692+
1693+
stmt = makeNode(CreateTrigStmt);
1694+
stmt->trigname = (char *) trigname;
1695+
stmt->relation = makeRangeVarFromRelid(relid);
1696+
stmt->funcname = func;
1697+
stmt->args = NIL;
1698+
stmt->row = true;
1699+
stmt->timing = TRIGGER_TYPE_BEFORE;
1700+
stmt->events = TRIGGER_TYPE_UPDATE;
1701+
stmt->columns = list_make1(makeString((char *) attname));
1702+
stmt->whenClause = NULL;
1703+
stmt->isconstraint = false;
1704+
stmt->deferrable = false;
1705+
stmt->initdeferred = false;
1706+
stmt->constrrel = NULL;
1707+
1708+
(void) CreateTrigger(stmt, NULL, InvalidOid, InvalidOid,
1709+
InvalidOid, InvalidOid, false);
1710+
}
1711+
1712+
/*
1713+
* Check if update trigger is enabled. Basicly it returns true if update
1714+
* trigger exists for parent table
1715+
*/
1716+
bool
1717+
is_update_trigger_enabled_internal(Oid parent)
1718+
{
1719+
char *trigname;
1720+
1721+
trigname = build_update_trigger_name_internal(parent);
1722+
return update_trigger_exists(parent, trigname);
1723+
}
1724+
1725+
static bool
1726+
update_trigger_exists(Oid relid, char *trigname)
1727+
{
1728+
bool res = false;
1729+
Relation tgrel;
1730+
SysScanDesc tgscan;
1731+
ScanKeyData key;
1732+
HeapTuple tuple;
1733+
1734+
tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
1735+
1736+
ScanKeyInit(&key,
1737+
Anum_pg_trigger_tgrelid,
1738+
BTEqualStrategyNumber, F_OIDEQ,
1739+
ObjectIdGetDatum(relid));
1740+
tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1741+
NULL, 1, &key);
1742+
while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1743+
{
1744+
Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
1745+
1746+
if (namestrcmp(&(pg_trigger->tgname), trigname) == 0)
1747+
{
1748+
res = true;
1749+
break;
1750+
}
1751+
}
1752+
systable_endscan(tgscan);
1753+
heap_close(tgrel, RowExclusiveLock);
1754+
1755+
return res;
1756+
}

src/partition_creation.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ Node * build_raw_hash_check_tree(char *attname,
7777

7878
void drop_check_constraint(Oid relid, AttrNumber attnum);
7979

80+
/* Update triggers */
81+
void create_single_update_trigger_internal(Oid relid,
82+
const char *trigname,
83+
const char *attname);
84+
bool is_update_trigger_enabled_internal(Oid parent);
85+
8086

8187
/* Partitioning callback type */
8288
typedef enum

0 commit comments

Comments
 (0)