From a7e274ccbf4f9bc2668e73d427f2e22b76922ea0 Mon Sep 17 00:00:00 2001 From: Jan Nidzwetzki Date: Tue, 27 Feb 2024 12:44:25 +0100 Subject: [PATCH] Fix missing varlen header in DimensionInfo The SQL data type _timescaledb_internal.dimension_info is declared with INTERNALLENGTH = VARIABLE. This requires a varlen header, which was missing. Therefore, the needed space of the function result was not handled properly. This commit introduces the missing header. --- src/dimension.c | 5 +++- src/dimension.h | 5 ++++ .../expected/hypertable_generalization.out | 25 +++++++++++++++++++ tsl/test/sql/hypertable_generalization.sql | 6 +++++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/dimension.c b/src/dimension.c index a3d82a3b981..136796ad63a 100644 --- a/src/dimension.c +++ b/src/dimension.c @@ -1748,7 +1748,10 @@ ts_dimension_info_out(PG_FUNCTION_ARGS) static DimensionInfo * make_dimension_info(Name colname, DimensionType dimtype) { - DimensionInfo *info = palloc0(sizeof(DimensionInfo)); + size_t size = sizeof(DimensionInfo); + DimensionInfo *info = palloc0(size); + SET_VARSIZE(info, size); + info->type = dimtype; namestrcpy(&info->colname, NameStr(*colname)); return info; diff --git a/src/dimension.h b/src/dimension.h index e58e6cfb660..ef8cba354be 100644 --- a/src/dimension.h +++ b/src/dimension.h @@ -93,6 +93,11 @@ typedef struct Hypertable Hypertable; */ typedef struct DimensionInfo { + /* We declare the SQL type dimension_info with INTERNALLENGTH = VARIABLE. + * So, PostgreSQL expects a proper length info field (varlena header). + */ + int32 vl_len_; + Oid table_relid; int32 dimension_id; NameData colname; diff --git a/tsl/test/expected/hypertable_generalization.out b/tsl/test/expected/hypertable_generalization.out index e0b6d032d37..afd23df8667 100644 --- a/tsl/test/expected/hypertable_generalization.out +++ b/tsl/test/expected/hypertable_generalization.out @@ -55,6 +55,31 @@ SELECT by_hash('id', 3, partition_func => 'part_func'); hash//id//3//part_func (1 row) +-- Check if we handle the varlength of the datatype properly +SELECT * FROM by_range('id') WHERE by_range IS NOT NULL; + by_range +----------------- + range//id//-//- +(1 row) + +SELECT * FROM by_range('id', partition_func => 'part_func') WHERE by_range IS NOT NULL; + by_range +------------------------- + range//id//-//part_func +(1 row) + +SELECT * FROM by_hash('id', 3) WHERE by_hash IS NOT NULL; + by_hash +---------------- + hash//id//3//- +(1 row) + +SELECT * FROM by_hash('id', 3, partition_func => 'part_func') WHERE by_hash IS NOT NULL; + by_hash +------------------------ + hash//id//3//part_func +(1 row) + \set ON_ERROR_STOP 0 SELECT 'hash//id//3//-'::_timescaledb_internal.dimension_info; ERROR: cannot construct type "dimension_info" from string at character 8 diff --git a/tsl/test/sql/hypertable_generalization.sql b/tsl/test/sql/hypertable_generalization.sql index 9f4207412cc..0ef91af24df 100644 --- a/tsl/test/sql/hypertable_generalization.sql +++ b/tsl/test/sql/hypertable_generalization.sql @@ -27,6 +27,12 @@ SELECT by_range('id', '1 week'::interval, 'part_func'::regproc); SELECT by_hash('id', 3); SELECT by_hash('id', 3, partition_func => 'part_func'); +-- Check if we handle the varlength of the datatype properly +SELECT * FROM by_range('id') WHERE by_range IS NOT NULL; +SELECT * FROM by_range('id', partition_func => 'part_func') WHERE by_range IS NOT NULL; +SELECT * FROM by_hash('id', 3) WHERE by_hash IS NOT NULL; +SELECT * FROM by_hash('id', 3, partition_func => 'part_func') WHERE by_hash IS NOT NULL; + \set ON_ERROR_STOP 0 SELECT 'hash//id//3//-'::_timescaledb_internal.dimension_info; SELECT by_range(NULL::name);