Skip to content

Commit 134bf2e

Browse files
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 b7d52ab commit 134bf2e

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"
@@ -150,12 +151,53 @@ pg_tde_ddl_command_start_capture(PG_FUNCTION_ARGS)
150151
else if (IsA(parsetree, CreateStmt))
151152
{
152153
CreateStmt *stmt = castNode(CreateStmt, parsetree);
154+
bool foundAccessMethod = false;
153155

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

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

160202
checkEncryptionStatus();
161203
}

0 commit comments

Comments
 (0)