Skip to content

Commit

Permalink
Fix search_path quoting in compression defaults function
Browse files Browse the repository at this point in the history
  • Loading branch information
svenklemm committed Jun 19, 2024
1 parent 6defa15 commit 42a12ee
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 27 deletions.
1 change: 1 addition & 0 deletions .unreleased/pr_7018
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixes: #7018 Fix search_path quoting in compression defaults function
23 changes: 23 additions & 0 deletions src/compat/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#define PG15_GE (PG_VERSION_NUM >= 150000)
#define PG16_LT (PG_VERSION_NUM < 160000)
#define PG16_GE (PG_VERSION_NUM >= 160000)
#define PG17_LT (PG_VERSION_NUM < 170000)

#if !(is_supported_pg_version(PG_VERSION_NUM))
#error "Unsupported PostgreSQL version"
Expand Down Expand Up @@ -765,3 +766,25 @@ error_severity(int elevel)
return prefix;
}
#endif

#if PG17_LT
/*
* Backport of RestrictSearchPath() from PG17
*
* We skip the check for IsBootstrapProcessingMode() since it creates problems
* on Windows builds and we don't need it for our use case.
*/
#include <utils/guc.h>
static inline void
RestrictSearchPath(void)
{
set_config_option("search_path",
"pg_catalog, pg_temp",
PGC_USERSET,
PGC_S_SESSION,
GUC_ACTION_SAVE,
true,
0,
false);
}
#endif
40 changes: 14 additions & 26 deletions tsl/src/compression/create.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <utils/array.h>
#include <utils/builtins.h>
#include <utils/datum.h>
#include <utils/guc.h>
#include <utils/rel.h>
#include <utils/syscache.h>
#include <utils/typcache.h>
Expand Down Expand Up @@ -908,7 +909,6 @@ compression_setting_segmentby_get_default(const Hypertable *ht)
ArrayType *column_res = NULL;
Datum datum;
text *message;
char *original_search_path = pstrdup(GetConfigOption("search_path", false, true));
bool isnull;
MemoryContext upper = CurrentMemoryContext;
MemoryContext old;
Expand All @@ -923,6 +923,10 @@ compression_setting_segmentby_get_default(const Hypertable *ht)
return NULL;
}

/* Lock down search_path */
int save_nestlevel = NewGUCNestLevel();
RestrictSearchPath();

initStringInfo(&command);
appendStringInfo(&command,
"SELECT "
Expand All @@ -938,11 +942,6 @@ compression_setting_segmentby_get_default(const Hypertable *ht)
if (SPI_connect() != SPI_OK_CONNECT)
elog(ERROR, "could not connect to SPI");

/* Lock down search_path */
res = SPI_exec("SET LOCAL search_path TO pg_catalog, pg_temp", 0);
if (res < 0)
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), (errmsg("could not set search_path"))));

res = SPI_execute(command.data, true /* read_only */, 0 /*count*/);

if (res < 0)
Expand Down Expand Up @@ -973,16 +972,11 @@ compression_setting_segmentby_get_default(const Hypertable *ht)
confidence = DatumGetInt32(datum);
}

/* Reset search path since this can be executed as part of a larger transaction */
resetStringInfo(&command);
appendStringInfo(&command, "SET LOCAL search_path TO %s", original_search_path);
res = SPI_exec(command.data, 0);
if (res < 0)
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), (errmsg("could not reset search_path"))));
pfree(original_search_path);

pfree(command.data);

/* Reset search path since this can be executed as part of a larger transaction */
AtEOXact_GUC(false, save_nestlevel);

res = SPI_finish();
if (res != SPI_OK_FINISH)
elog(ERROR, "SPI_finish failed: %s", SPI_result_code_string(res));
Expand Down Expand Up @@ -1020,7 +1014,6 @@ compression_setting_orderby_get_default(Hypertable *ht, ArrayType *segmentby)
MemoryContext upper = CurrentMemoryContext;
MemoryContext old;
char *orderby;
char *original_search_path = pstrdup(GetConfigOption("search_path", false, true));
int32 confidence = -1;

Oid types[] = { TEXTARRAYOID };
Expand All @@ -1039,6 +1032,10 @@ compression_setting_orderby_get_default(Hypertable *ht, ArrayType *segmentby)
return obs;
}

/* Lock down search_path */
int save_nestlevel = NewGUCNestLevel();
RestrictSearchPath();

initStringInfo(&command);
appendStringInfo(&command,
"SELECT "
Expand All @@ -1055,11 +1052,6 @@ compression_setting_orderby_get_default(Hypertable *ht, ArrayType *segmentby)
if (SPI_connect() != SPI_OK_CONNECT)
elog(ERROR, "could not connect to SPI");

/* Lock down search_path */
res = SPI_exec("SET LOCAL search_path TO pg_catalog, pg_temp", 0);
if (res < 0)
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), (errmsg("could not set search_path"))));

res = SPI_execute_with_args(command.data,
1,
types,
Expand Down Expand Up @@ -1096,12 +1088,8 @@ compression_setting_orderby_get_default(Hypertable *ht, ArrayType *segmentby)
}

/* Reset search path since this can be executed as part of a larger transaction */
resetStringInfo(&command);
appendStringInfo(&command, "SET LOCAL search_path TO %s", original_search_path);
res = SPI_exec(command.data, 0);
if (res < 0)
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), (errmsg("could not reset search_path"))));
pfree(original_search_path);
AtEOXact_GUC(false, save_nestlevel);

pfree(command.data);

res = SPI_finish();
Expand Down
13 changes: 13 additions & 0 deletions tsl/test/expected/compression_defaults.out
Original file line number Diff line number Diff line change
Expand Up @@ -397,3 +397,16 @@ SET timescaledb.compression_orderby_default_function = '_timescaledb_functions.g
SET timescaledb.compression_segmentby_default_function = '_timescaledb_functions.get_segmentby_defaults';
RESET timescaledb.compression_segmentby_default_function;
RESET timescaledb.compression_orderby_default_function;
-- test search_path quoting
SET search_path TO '';
CREATE TABLE public.t1 (time timestamptz NOT NULL, segment_value text NOT NULL);
SELECT public.create_hypertable('public.t1', 'time');
create_hypertable
-------------------
(13,public,t1,t)
(1 row)

ALTER TABLE public.t1 SET (timescaledb.compress, timescaledb.compress_orderby = 'segment_value');
WARNING: there was some uncertainty picking the default segment by for the hypertable: You do not have any indexes on columns that can be used for segment_by and thus we are not using segment_by for compression. Please make sure you are not missing any indexes
NOTICE: default segment by for hypertable "t1" is set to ""
RESET search_path;
9 changes: 8 additions & 1 deletion tsl/test/sql/compression_defaults.sql
Original file line number Diff line number Diff line change
Expand Up @@ -206,4 +206,11 @@ SET timescaledb.compression_orderby_default_function = '_timescaledb_functions.g
SET timescaledb.compression_orderby_default_function = '_timescaledb_functions.get_orderby_defaults';
SET timescaledb.compression_segmentby_default_function = '_timescaledb_functions.get_segmentby_defaults';
RESET timescaledb.compression_segmentby_default_function;
RESET timescaledb.compression_orderby_default_function;
RESET timescaledb.compression_orderby_default_function;

-- test search_path quoting
SET search_path TO '';
CREATE TABLE public.t1 (time timestamptz NOT NULL, segment_value text NOT NULL);
SELECT public.create_hypertable('public.t1', 'time');
ALTER TABLE public.t1 SET (timescaledb.compress, timescaledb.compress_orderby = 'segment_value');
RESET search_path;

0 comments on commit 42a12ee

Please sign in to comment.