Skip to content

Commit 050d87e

Browse files
author
Anders Åstrand
committed
PG-1504 Make partitions inherit encryption status
Since the access method isn't included in the statement we'll have to look it up on the parent in the same way DefineRelation() does.
1 parent 23786e9 commit 050d87e

File tree

3 files changed

+141
-1
lines changed

3 files changed

+141
-1
lines changed

contrib/pg_tde/expected/partition_table.out

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,64 @@ SELECT pg_tde_is_encrypted('partition_q4_2024');
8787
(1 row)
8888

8989
DROP TABLE partitioned_table;
90+
-- Partition inherits encryption status from parent table if default is heap and parent is tde_heap
91+
SET default_table_access_method = "heap";
92+
CREATE TABLE partition_parent (a int) PARTITION BY RANGE (a) USING tde_heap;
93+
CREATE TABLE partition_child PARTITION OF partition_parent FOR VALUES FROM (0) TO (9);
94+
SELECT pg_tde_is_encrypted('partition_child');
95+
pg_tde_is_encrypted
96+
---------------------
97+
t
98+
(1 row)
99+
100+
DROP TABLE partition_parent;
101+
RESET default_table_access_method;
102+
-- Partition inherits encryption status from parent table if default is tde_heap and parent is heap
103+
SET default_table_access_method = "tde_heap";
104+
CREATE TABLE partition_parent (a int) PARTITION BY RANGE (a) USING heap;
105+
CREATE TABLE partition_child PARTITION OF partition_parent FOR VALUES FROM (0) TO (9);
106+
SELECT pg_tde_is_encrypted('partition_child');
107+
pg_tde_is_encrypted
108+
---------------------
109+
f
110+
(1 row)
111+
112+
DROP TABLE partition_parent;
113+
RESET default_table_access_method;
114+
-- Partition uses default access method to determine encryption status if neither parent nor child have an access method set
115+
CREATE TABLE partition_parent (a int) PARTITION BY RANGE (a);
116+
SET default_table_access_method = "tde_heap";
117+
CREATE TABLE partition_child_tde PARTITION OF partition_parent FOR VALUES FROM (0) TO (9);
118+
SELECT pg_tde_is_encrypted('partition_child_tde');
119+
pg_tde_is_encrypted
120+
---------------------
121+
t
122+
(1 row)
123+
124+
SET default_table_access_method = "heap";
125+
CREATE TABLE partition_child_heap PARTITION OF partition_parent FOR VALUES FROM (10) TO (19);
126+
SELECT pg_tde_is_encrypted('partition_child_heap');
127+
pg_tde_is_encrypted
128+
---------------------
129+
f
130+
(1 row)
131+
132+
DROP TABLE partition_parent;
133+
RESET default_table_access_method;
134+
-- Enforce encryption GUC is respected when creating partitions even if parent is plain text
135+
CREATE TABLE partition_parent (a int) PARTITION BY RANGE (a) USING heap;
136+
SET pg_tde.enforce_encryption = on;
137+
CREATE TABLE partition_child_inherit PARTITION OF partition_parent FOR VALUES FROM (0) TO (10);
138+
ERROR: pg_tde.enforce_encryption is ON, only the tde_heap access method is allowed.
139+
CREATE TABLE partition_child_heap PARTITION OF partition_parent FOR VALUES FROM (11) TO (20) USING heap;
140+
ERROR: pg_tde.enforce_encryption is ON, only the tde_heap access method is allowed.
141+
CREATE TABLE partition_child_tde_heap PARTITION OF partition_parent FOR VALUES FROM (11) TO (20) USING tde_heap;
142+
SELECT pg_tde_is_encrypted('partition_child_tde_heap');
143+
pg_tde_is_encrypted
144+
---------------------
145+
t
146+
(1 row)
147+
148+
DROP TABLE partition_parent;
149+
RESET pg_tde.enforce_encryption;
90150
DROP EXTENSION pg_tde;

contrib/pg_tde/sql/partition_table.sql

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,42 @@ SELECT pg_tde_is_encrypted('partition_q3_2024');
3232
SELECT pg_tde_is_encrypted('partition_q4_2024');
3333

3434
DROP TABLE partitioned_table;
35+
36+
-- Partition inherits encryption status from parent table if default is heap and parent is tde_heap
37+
SET default_table_access_method = "heap";
38+
CREATE TABLE partition_parent (a int) PARTITION BY RANGE (a) USING tde_heap;
39+
CREATE TABLE partition_child PARTITION OF partition_parent FOR VALUES FROM (0) TO (9);
40+
SELECT pg_tde_is_encrypted('partition_child');
41+
DROP TABLE partition_parent;
42+
RESET default_table_access_method;
43+
44+
-- Partition inherits encryption status from parent table if default is tde_heap and parent is heap
45+
SET default_table_access_method = "tde_heap";
46+
CREATE TABLE partition_parent (a int) PARTITION BY RANGE (a) USING heap;
47+
CREATE TABLE partition_child PARTITION OF partition_parent FOR VALUES FROM (0) TO (9);
48+
SELECT pg_tde_is_encrypted('partition_child');
49+
DROP TABLE partition_parent;
50+
RESET default_table_access_method;
51+
52+
-- Partition uses default access method to determine encryption status if neither parent nor child have an access method set
53+
CREATE TABLE partition_parent (a int) PARTITION BY RANGE (a);
54+
SET default_table_access_method = "tde_heap";
55+
CREATE TABLE partition_child_tde PARTITION OF partition_parent FOR VALUES FROM (0) TO (9);
56+
SELECT pg_tde_is_encrypted('partition_child_tde');
57+
SET default_table_access_method = "heap";
58+
CREATE TABLE partition_child_heap PARTITION OF partition_parent FOR VALUES FROM (10) TO (19);
59+
SELECT pg_tde_is_encrypted('partition_child_heap');
60+
DROP TABLE partition_parent;
61+
RESET default_table_access_method;
62+
63+
-- Enforce encryption GUC is respected when creating partitions even if parent is plain text
64+
CREATE TABLE partition_parent (a int) PARTITION BY RANGE (a) USING heap;
65+
SET pg_tde.enforce_encryption = on;
66+
CREATE TABLE partition_child_inherit PARTITION OF partition_parent FOR VALUES FROM (0) TO (10);
67+
CREATE TABLE partition_child_heap PARTITION OF partition_parent FOR VALUES FROM (11) TO (20) USING heap;
68+
CREATE TABLE partition_child_tde_heap PARTITION OF partition_parent FOR VALUES FROM (11) TO (20) USING tde_heap;
69+
SELECT pg_tde_is_encrypted('partition_child_tde_heap');
70+
DROP TABLE partition_parent;
71+
RESET pg_tde.enforce_encryption;
72+
3573
DROP EXTENSION pg_tde;

contrib/pg_tde/src/pg_tde_event_capture.c

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "fmgr.h"
1515
#include "utils/rel.h"
1616
#include "utils/builtins.h"
17+
#include "utils/lsyscache.h"
1718
#include "catalog/pg_class.h"
1819
#include "commands/defrem.h"
1920
#include "commands/sequence.h"
@@ -149,12 +150,53 @@ pg_tde_ddl_command_start_capture(PG_FUNCTION_ARGS)
149150
else if (IsA(parsetree, CreateStmt))
150151
{
151152
CreateStmt *stmt = castNode(CreateStmt, parsetree);
153+
bool foundAccessMethod = false;
152154

153155
validateCurrentEventTriggerState(true);
154156
tdeCurrentCreateEvent.tid = GetCurrentFullTransactionId();
155157

156-
if (shouldEncryptTable(stmt->accessMethod))
158+
159+
if (stmt->accessMethod)
160+
{
161+
foundAccessMethod = true;
162+
if (strcmp(stmt->accessMethod, "tde_heap") == 0)
163+
{
164+
tdeCurrentCreateEvent.encryptMode = true;
165+
}
166+
}
167+
else if (stmt->partbound)
168+
{
169+
/*
170+
* If no access method is specified, and this is a partition of a
171+
* parent table, access method can be inherited from the parent
172+
* table if it has one set.
173+
*
174+
* AccessExclusiveLock might seem excessive, but it's what
175+
* DefineRelation() will take on any partitioned parent relation
176+
* in this transaction anyway.
177+
*/
178+
Oid parentOid;
179+
Oid parentAmOid;
180+
181+
Assert(list_length(stmt->inhRelations) == 1);
182+
183+
parentOid = RangeVarGetRelid(linitial(stmt->inhRelations),
184+
AccessExclusiveLock,
185+
false);
186+
parentAmOid = get_rel_relam(parentOid);
187+
foundAccessMethod = parentAmOid != InvalidOid;
188+
189+
if (foundAccessMethod && parentAmOid == get_tde_table_am_oid())
190+
{
191+
tdeCurrentCreateEvent.encryptMode = true;
192+
}
193+
}
194+
195+
if (!foundAccessMethod
196+
&& strcmp(default_table_access_method, "tde_heap") == 0)
197+
{
157198
tdeCurrentCreateEvent.encryptMode = true;
199+
}
158200

159201
checkEncryptionStatus();
160202
}

0 commit comments

Comments
 (0)