Skip to content

Commit 5fb5bef

Browse files
committed
Allow TAM chunk creation as non-owner
When using Hypercore TAM on the hypertable, new chunks are created as hypercore chunks, including the compressed relation. This means that the compressed relation is created as the inserting user. However, if the inserting user is not the table owner, this operation failed. The reason it failed was because some toast settings were changed on the compressed chunk during its creation without switching to a role with proper permissions. This is easily fixed by extending the section of code that is executed under the permissive role.
1 parent 37eddfb commit 5fb5bef

File tree

4 files changed

+139
-2
lines changed

4 files changed

+139
-2
lines changed

test/runner.sh

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ if mkdir ${TEST_OUTPUT_DIR}/.pg_init 2>/dev/null; then
8282
8383
ALTER USER ${TEST_ROLE_SUPERUSER} WITH SUPERUSER;
8484
ALTER USER ${TEST_ROLE_CLUSTER_SUPERUSER} WITH SUPERUSER;
85+
ALTER USER ${TEST_ROLE_DEFAULT_PERM_USER} WITH CREATEROLE;
8586
ALTER USER ${TEST_ROLE_1} WITH CREATEDB CREATEROLE;
8687
ALTER USER ${TEST_ROLE_2} WITH CREATEDB PASSWORD '${TEST_ROLE_2_PASS}';
8788
ALTER USER ${TEST_ROLE_3} WITH CREATEDB PASSWORD '${TEST_ROLE_3_PASS}';

tsl/src/compression/compression_storage.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,11 @@ compression_chunk_create(Chunk *src_chunk, Chunk *chunk, List *column_defs, Oid
139139
transformRelOptions((Datum) 0, create->options, "toast", validnsps, true, false);
140140
(void) heap_reloptions(RELKIND_TOASTVALUE, toast_options, true);
141141
NewRelationCreateToastTable(chunk->table_id, toast_options);
142-
ts_catalog_restore_user(&sec_ctx);
143-
modify_compressed_toast_table_storage(settings, column_defs, chunk->table_id);
144142

143+
modify_compressed_toast_table_storage(settings, column_defs, chunk->table_id);
145144
set_statistics_on_compressed_chunk(chunk->table_id);
146145
set_toast_tuple_target_on_chunk(chunk->table_id);
146+
ts_catalog_restore_user(&sec_ctx);
147147

148148
create_compressed_chunk_indexes(chunk, settings);
149149

tsl/test/expected/hypercore_create.out

+79
Original file line numberDiff line numberDiff line change
@@ -1097,3 +1097,82 @@ select count(*) from :chunk;
10971097
(1 row)
10981098

10991099
\set ON_ERROR_STOP 1
1100+
set timescaledb.enable_transparent_decompression=true;
1101+
-- Test chunk creation with non-owner user
1102+
CREATE TABLE conditions ( -- create a regular table
1103+
time timestamptz not null,
1104+
location text not null,
1105+
temperature double precision null
1106+
);
1107+
select create_hypertable('conditions', 'time'); -- turn it into a hypertable
1108+
create_hypertable
1109+
--------------------------
1110+
(12,public,conditions,t)
1111+
(1 row)
1112+
1113+
-------------------------------------------------------------------------------
1114+
-- Create a new user and grant privileges to work on conditions
1115+
-------------------------------------------------------------------------------
1116+
create role testuser;
1117+
-- Grant ability to switch to testuser
1118+
grant testuser to :ROLE_DEFAULT_PERM_USER;
1119+
grant select,insert,update,delete on conditions to testuser;
1120+
alter table conditions set (
1121+
timescaledb.compress,
1122+
timescaledb.compress_segmentby = 'location,temperature',
1123+
timescaledb.compress_orderby = 'time'
1124+
);
1125+
-------------------------------------------------------------------------------
1126+
-- Set hypercore access method on the hypertable
1127+
-------------------------------------------------------------------------------
1128+
alter table conditions set access method hypercore;
1129+
-- Switch to testuser and make sure it can insert into conditions
1130+
set role testuser;
1131+
select current_user;
1132+
current_user
1133+
--------------
1134+
testuser
1135+
(1 row)
1136+
1137+
select * from show_chunks('conditions') ch
1138+
join _timescaledb_catalog.compression_settings cs on (cs.relid = ch);
1139+
ch | relid | compress_relid | segmentby | orderby | orderby_desc | orderby_nullsfirst
1140+
----+-------+----------------+-----------+---------+--------------+--------------------
1141+
(0 rows)
1142+
1143+
-- An insert should create a new hypercore chunk, including the compressed chunk
1144+
insert into conditions values ('2024-01-02', 'school', 99.5);
1145+
select chunk, amname, cs.compress_relid
1146+
from show_chunks('conditions') as chunk
1147+
join pg_class on (pg_class.oid = chunk)
1148+
join pg_am on (relam = pg_am.oid)
1149+
join _timescaledb_catalog.compression_settings cs on (cs.relid = chunk);
1150+
chunk | amname | compress_relid
1151+
------------------------------------------+-----------+--------------------------------------------------
1152+
_timescaledb_internal._hyper_12_49_chunk | hypercore | _timescaledb_internal.compress_hyper_13_50_chunk
1153+
(1 row)
1154+
1155+
-- Data is not compressed
1156+
select _timescaledb_debug.is_compressed_tid(ctid), * from conditions;
1157+
is_compressed_tid | time | location | temperature
1158+
-------------------+------------------------------+----------+-------------
1159+
f | Tue Jan 02 00:00:00 2024 PST | school | 99.5
1160+
(1 row)
1161+
1162+
select compress_chunk(ch) from show_chunks('conditions') ch;
1163+
compress_chunk
1164+
------------------------------------------
1165+
_timescaledb_internal._hyper_12_49_chunk
1166+
(1 row)
1167+
1168+
-- Now the data is compressed
1169+
select _timescaledb_debug.is_compressed_tid(ctid), * from conditions;
1170+
is_compressed_tid | time | location | temperature
1171+
-------------------+------------------------------+----------+-------------
1172+
t | Tue Jan 02 00:00:00 2024 PST | school | 99.5
1173+
(1 row)
1174+
1175+
reset role;
1176+
-- Need to revoke privileges to drop user
1177+
revoke all on conditions from testuser;
1178+
drop role testuser;

tsl/test/sql/hypercore_create.sql

+57
Original file line numberDiff line numberDiff line change
@@ -529,3 +529,60 @@ alter table :chunk set access method heap;
529529
vacuum full :chunk;
530530
select count(*) from :chunk;
531531
\set ON_ERROR_STOP 1
532+
533+
set timescaledb.enable_transparent_decompression=true;
534+
535+
-- Test chunk creation with non-owner user
536+
CREATE TABLE conditions ( -- create a regular table
537+
time timestamptz not null,
538+
location text not null,
539+
temperature double precision null
540+
);
541+
542+
select create_hypertable('conditions', 'time'); -- turn it into a hypertable
543+
544+
-------------------------------------------------------------------------------
545+
-- Create a new user and grant privileges to work on conditions
546+
-------------------------------------------------------------------------------
547+
create role testuser;
548+
-- Grant ability to switch to testuser
549+
grant testuser to :ROLE_DEFAULT_PERM_USER;
550+
grant select,insert,update,delete on conditions to testuser;
551+
552+
alter table conditions set (
553+
timescaledb.compress,
554+
timescaledb.compress_segmentby = 'location,temperature',
555+
timescaledb.compress_orderby = 'time'
556+
);
557+
558+
559+
-------------------------------------------------------------------------------
560+
-- Set hypercore access method on the hypertable
561+
-------------------------------------------------------------------------------
562+
alter table conditions set access method hypercore;
563+
564+
-- Switch to testuser and make sure it can insert into conditions
565+
set role testuser;
566+
select current_user;
567+
select * from show_chunks('conditions') ch
568+
join _timescaledb_catalog.compression_settings cs on (cs.relid = ch);
569+
570+
-- An insert should create a new hypercore chunk, including the compressed chunk
571+
insert into conditions values ('2024-01-02', 'school', 99.5);
572+
573+
select chunk, amname, cs.compress_relid
574+
from show_chunks('conditions') as chunk
575+
join pg_class on (pg_class.oid = chunk)
576+
join pg_am on (relam = pg_am.oid)
577+
join _timescaledb_catalog.compression_settings cs on (cs.relid = chunk);
578+
579+
-- Data is not compressed
580+
select _timescaledb_debug.is_compressed_tid(ctid), * from conditions;
581+
select compress_chunk(ch) from show_chunks('conditions') ch;
582+
-- Now the data is compressed
583+
select _timescaledb_debug.is_compressed_tid(ctid), * from conditions;
584+
reset role;
585+
586+
-- Need to revoke privileges to drop user
587+
revoke all on conditions from testuser;
588+
drop role testuser;

0 commit comments

Comments
 (0)