mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-18 19:59:48 +08:00
Fix subtract_integer_from_now on 32-bit platforms
This patch fixes subtract_integer_from_now on 32-bit platforms, improves error handling and adds some basic tests. subtract_integer_from_now would trigger an assert when called on a hypertable without integer time dimension (found by sqlsmith). Additionally subtract_integer_from_now would segfault when called on a hypertable without partitioning dimensions.
This commit is contained in:
parent
a760887145
commit
39645d56da
@ -2391,6 +2391,11 @@ ts_hypertable_set_integer_now_func(PG_FUNCTION_ARGS)
|
|||||||
ts_hypertable_permissions_check(table_relid, GetUserId());
|
ts_hypertable_permissions_check(table_relid, GetUserId());
|
||||||
hypertable = ts_hypertable_cache_get_cache_and_entry(table_relid, CACHE_FLAG_NONE, &hcache);
|
hypertable = ts_hypertable_cache_get_cache_and_entry(table_relid, CACHE_FLAG_NONE, &hcache);
|
||||||
|
|
||||||
|
if (TS_HYPERTABLE_IS_INTERNAL_COMPRESSION_TABLE(hypertable))
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
|
errmsg("custom time function not supported on internal compression table")));
|
||||||
|
|
||||||
/* validate that the open dimension uses numeric type */
|
/* validate that the open dimension uses numeric type */
|
||||||
open_dim = hyperspace_get_open_dimension(hypertable->space, 0);
|
open_dim = hyperspace_get_open_dimension(hypertable->space, 0);
|
||||||
|
|
||||||
|
28
src/utils.c
28
src/utils.c
@ -904,18 +904,24 @@ Datum
|
|||||||
ts_subtract_integer_from_now(PG_FUNCTION_ARGS)
|
ts_subtract_integer_from_now(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Oid ht_relid = PG_GETARG_OID(0);
|
Oid ht_relid = PG_GETARG_OID(0);
|
||||||
Datum lag = PG_GETARG_INT64(1);
|
int64 lag = PG_GETARG_INT64(1);
|
||||||
Cache *hcache;
|
Cache *hcache;
|
||||||
Hypertable *hypertable =
|
Hypertable *ht = ts_hypertable_cache_get_cache_and_entry(ht_relid, CACHE_FLAG_NONE, &hcache);
|
||||||
ts_hypertable_cache_get_cache_and_entry(ht_relid, CACHE_FLAG_NONE, &hcache);
|
const Dimension *dim = hyperspace_get_open_dimension(ht->space, 0);
|
||||||
|
|
||||||
const Dimension *dim = hyperspace_get_open_dimension(hypertable->space, 0);
|
|
||||||
Oid partitioning_type = ts_dimension_get_partition_type(dim);
|
|
||||||
Oid now_func = ts_get_integer_now_func(dim);
|
|
||||||
if (now_func == InvalidOid)
|
|
||||||
elog(ERROR, "could not find valid integer_now function for hypertable");
|
|
||||||
Assert(IS_INTEGER_TYPE(partitioning_type));
|
|
||||||
int64 res = ts_sub_integer_from_now(lag, partitioning_type, now_func);
|
|
||||||
ts_cache_release(hcache);
|
ts_cache_release(hcache);
|
||||||
|
|
||||||
|
if (!dim)
|
||||||
|
elog(ERROR, "hypertable has no open partitioning dimension");
|
||||||
|
|
||||||
|
Oid partitioning_type = ts_dimension_get_partition_type(dim);
|
||||||
|
|
||||||
|
if (!IS_INTEGER_TYPE(partitioning_type))
|
||||||
|
elog(ERROR, "hypertable has no integer partitioning dimension");
|
||||||
|
|
||||||
|
Oid now_func = ts_get_integer_now_func(dim);
|
||||||
|
if (!OidIsValid(now_func))
|
||||||
|
elog(ERROR, "could not find valid integer_now function for hypertable");
|
||||||
|
|
||||||
|
int64 res = ts_sub_integer_from_now(lag, partitioning_type, now_func);
|
||||||
return Int64GetDatum(res);
|
return Int64GetDatum(res);
|
||||||
}
|
}
|
||||||
|
118
tsl/test/shared/expected/subtract_integer_from_now.out
Normal file
118
tsl/test/shared/expected/subtract_integer_from_now.out
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
-- This file and its contents are licensed under the Timescale License.
|
||||||
|
-- Please see the included NOTICE for copyright information and
|
||||||
|
-- LICENSE-TIMESCALE for a copy of the license.
|
||||||
|
-- test on normal table
|
||||||
|
\set ON_ERROR_STOP 0
|
||||||
|
SELECT _timescaledb_internal.subtract_integer_from_now('pg_class', 1);
|
||||||
|
ERROR: table "pg_class" is not a hypertable
|
||||||
|
\set ON_ERROR_STOP 1
|
||||||
|
-- test on hypertable with non-int time dimension
|
||||||
|
\set ON_ERROR_STOP 0
|
||||||
|
SELECT _timescaledb_internal.subtract_integer_from_now('metrics', 1);
|
||||||
|
ERROR: hypertable has no integer partitioning dimension
|
||||||
|
\set ON_ERROR_STOP 1
|
||||||
|
SELECT
|
||||||
|
format('%I.%I', ht.schema_name, ht.table_name) AS "TABLENAME"
|
||||||
|
FROM
|
||||||
|
_timescaledb_catalog.hypertable ht
|
||||||
|
INNER JOIN _timescaledb_catalog.hypertable uncompress ON (ht.id = uncompress.compressed_hypertable_id
|
||||||
|
AND uncompress.table_name = 'metrics_compressed') \gset
|
||||||
|
-- test on hypertable without dimensions
|
||||||
|
\set ON_ERROR_STOP 0
|
||||||
|
SELECT _timescaledb_internal.subtract_integer_from_now(:'TABLENAME', 1);
|
||||||
|
ERROR: hypertable has no open partitioning dimension
|
||||||
|
\set ON_ERROR_STOP 1
|
||||||
|
-- test on hypertable without now function
|
||||||
|
CREATE TABLE subtract_int_no_func(time int NOT NULL);
|
||||||
|
SELECT table_name FROM create_hypertable('subtract_int_no_func','time',chunk_time_interval:=10);
|
||||||
|
table_name
|
||||||
|
----------------------
|
||||||
|
subtract_int_no_func
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
\set ON_ERROR_STOP 0
|
||||||
|
SELECT _timescaledb_internal.subtract_integer_from_now('subtract_int_no_func', 1);
|
||||||
|
ERROR: integer_now function not set
|
||||||
|
\set ON_ERROR_STOP 1
|
||||||
|
CREATE OR REPLACE FUNCTION sub_int2_now() RETURNS int2 AS $$ SELECT 2::int2; $$ LANGUAGE SQL IMMUTABLE;
|
||||||
|
CREATE OR REPLACE FUNCTION sub_int4_now() RETURNS int4 AS $$ SELECT 4::int4; $$ LANGUAGE SQL IMMUTABLE;
|
||||||
|
CREATE OR REPLACE FUNCTION sub_int8_now() RETURNS int8 AS $$ SELECT 8::int8; $$ LANGUAGE SQL IMMUTABLE;
|
||||||
|
CREATE TABLE subtract_int2(time int2 NOT NULL);
|
||||||
|
CREATE TABLE subtract_int4(time int4 NOT NULL);
|
||||||
|
CREATE TABLE subtract_int8(time int8 NOT NULL);
|
||||||
|
SELECT table_name FROM create_hypertable('subtract_int2', 'time', chunk_time_interval:=10);
|
||||||
|
table_name
|
||||||
|
---------------
|
||||||
|
subtract_int2
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT table_name FROM create_hypertable('subtract_int4', 'time', chunk_time_interval:=10);
|
||||||
|
table_name
|
||||||
|
---------------
|
||||||
|
subtract_int4
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT table_name FROM create_hypertable('subtract_int8', 'time', chunk_time_interval:=10);
|
||||||
|
table_name
|
||||||
|
---------------
|
||||||
|
subtract_int8
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT set_integer_now_func('subtract_int2', 'sub_int2_now');
|
||||||
|
set_integer_now_func
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT set_integer_now_func('subtract_int4', 'sub_int4_now');
|
||||||
|
set_integer_now_func
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT set_integer_now_func('subtract_int8', 'sub_int8_now');
|
||||||
|
set_integer_now_func
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT _timescaledb_internal.subtract_integer_from_now('subtract_int2', lag) AS sub FROM (VALUES (-10),(0),(2),(4),(8)) v(lag);
|
||||||
|
sub
|
||||||
|
-----
|
||||||
|
12
|
||||||
|
2
|
||||||
|
0
|
||||||
|
-2
|
||||||
|
-6
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
SELECT _timescaledb_internal.subtract_integer_from_now('subtract_int4', lag) AS sub FROM (VALUES (-10),(0),(2),(4),(8)) v(lag);
|
||||||
|
sub
|
||||||
|
-----
|
||||||
|
14
|
||||||
|
4
|
||||||
|
2
|
||||||
|
0
|
||||||
|
-4
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
SELECT _timescaledb_internal.subtract_integer_from_now('subtract_int8', lag) AS sub FROM (VALUES (-10),(0),(2),(4),(8)) v(lag);
|
||||||
|
sub
|
||||||
|
-----
|
||||||
|
18
|
||||||
|
8
|
||||||
|
6
|
||||||
|
4
|
||||||
|
0
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
-- test set_integer_now_func on internal table
|
||||||
|
\set ON_ERROR_STOP 0
|
||||||
|
SELECT set_integer_now_func(:'TABLENAME', 'sub_int2_now');
|
||||||
|
ERROR: custom time function not supported on internal compression table
|
||||||
|
\set ON_ERROR_STOP 1
|
||||||
|
-- cleanup
|
||||||
|
DROP TABLE subtract_int_no_func;
|
||||||
|
DROP TABLE subtract_int2;
|
||||||
|
DROP TABLE subtract_int4;
|
||||||
|
DROP TABLE subtract_int8;
|
@ -9,7 +9,8 @@ set(TEST_FILES_SHARED
|
|||||||
dist_fetcher_type.sql
|
dist_fetcher_type.sql
|
||||||
dist_gapfill.sql
|
dist_gapfill.sql
|
||||||
dist_insert.sql
|
dist_insert.sql
|
||||||
dist_queries.sql)
|
dist_queries.sql
|
||||||
|
subtract_integer_from_now.sql)
|
||||||
|
|
||||||
if((${PG_VERSION_MAJOR} GREATER_EQUAL "14"))
|
if((${PG_VERSION_MAJOR} GREATER_EQUAL "14"))
|
||||||
list(APPEND TEST_FILES_SHARED memoize.sql)
|
list(APPEND TEST_FILES_SHARED memoize.sql)
|
||||||
|
63
tsl/test/shared/sql/subtract_integer_from_now.sql
Normal file
63
tsl/test/shared/sql/subtract_integer_from_now.sql
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
-- This file and its contents are licensed under the Timescale License.
|
||||||
|
-- Please see the included NOTICE for copyright information and
|
||||||
|
-- LICENSE-TIMESCALE for a copy of the license.
|
||||||
|
|
||||||
|
-- test on normal table
|
||||||
|
\set ON_ERROR_STOP 0
|
||||||
|
SELECT _timescaledb_internal.subtract_integer_from_now('pg_class', 1);
|
||||||
|
\set ON_ERROR_STOP 1
|
||||||
|
|
||||||
|
-- test on hypertable with non-int time dimension
|
||||||
|
\set ON_ERROR_STOP 0
|
||||||
|
SELECT _timescaledb_internal.subtract_integer_from_now('metrics', 1);
|
||||||
|
\set ON_ERROR_STOP 1
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
format('%I.%I', ht.schema_name, ht.table_name) AS "TABLENAME"
|
||||||
|
FROM
|
||||||
|
_timescaledb_catalog.hypertable ht
|
||||||
|
INNER JOIN _timescaledb_catalog.hypertable uncompress ON (ht.id = uncompress.compressed_hypertable_id
|
||||||
|
AND uncompress.table_name = 'metrics_compressed') \gset
|
||||||
|
|
||||||
|
-- test on hypertable without dimensions
|
||||||
|
\set ON_ERROR_STOP 0
|
||||||
|
SELECT _timescaledb_internal.subtract_integer_from_now(:'TABLENAME', 1);
|
||||||
|
\set ON_ERROR_STOP 1
|
||||||
|
|
||||||
|
-- test on hypertable without now function
|
||||||
|
CREATE TABLE subtract_int_no_func(time int NOT NULL);
|
||||||
|
SELECT table_name FROM create_hypertable('subtract_int_no_func','time',chunk_time_interval:=10);
|
||||||
|
\set ON_ERROR_STOP 0
|
||||||
|
SELECT _timescaledb_internal.subtract_integer_from_now('subtract_int_no_func', 1);
|
||||||
|
\set ON_ERROR_STOP 1
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION sub_int2_now() RETURNS int2 AS $$ SELECT 2::int2; $$ LANGUAGE SQL IMMUTABLE;
|
||||||
|
CREATE OR REPLACE FUNCTION sub_int4_now() RETURNS int4 AS $$ SELECT 4::int4; $$ LANGUAGE SQL IMMUTABLE;
|
||||||
|
CREATE OR REPLACE FUNCTION sub_int8_now() RETURNS int8 AS $$ SELECT 8::int8; $$ LANGUAGE SQL IMMUTABLE;
|
||||||
|
|
||||||
|
CREATE TABLE subtract_int2(time int2 NOT NULL);
|
||||||
|
CREATE TABLE subtract_int4(time int4 NOT NULL);
|
||||||
|
CREATE TABLE subtract_int8(time int8 NOT NULL);
|
||||||
|
|
||||||
|
SELECT table_name FROM create_hypertable('subtract_int2', 'time', chunk_time_interval:=10);
|
||||||
|
SELECT table_name FROM create_hypertable('subtract_int4', 'time', chunk_time_interval:=10);
|
||||||
|
SELECT table_name FROM create_hypertable('subtract_int8', 'time', chunk_time_interval:=10);
|
||||||
|
|
||||||
|
SELECT set_integer_now_func('subtract_int2', 'sub_int2_now');
|
||||||
|
SELECT set_integer_now_func('subtract_int4', 'sub_int4_now');
|
||||||
|
SELECT set_integer_now_func('subtract_int8', 'sub_int8_now');
|
||||||
|
|
||||||
|
SELECT _timescaledb_internal.subtract_integer_from_now('subtract_int2', lag) AS sub FROM (VALUES (-10),(0),(2),(4),(8)) v(lag);
|
||||||
|
SELECT _timescaledb_internal.subtract_integer_from_now('subtract_int4', lag) AS sub FROM (VALUES (-10),(0),(2),(4),(8)) v(lag);
|
||||||
|
SELECT _timescaledb_internal.subtract_integer_from_now('subtract_int8', lag) AS sub FROM (VALUES (-10),(0),(2),(4),(8)) v(lag);
|
||||||
|
|
||||||
|
-- test set_integer_now_func on internal table
|
||||||
|
\set ON_ERROR_STOP 0
|
||||||
|
SELECT set_integer_now_func(:'TABLENAME', 'sub_int2_now');
|
||||||
|
\set ON_ERROR_STOP 1
|
||||||
|
|
||||||
|
-- cleanup
|
||||||
|
DROP TABLE subtract_int_no_func;
|
||||||
|
DROP TABLE subtract_int2;
|
||||||
|
DROP TABLE subtract_int4;
|
||||||
|
DROP TABLE subtract_int8;
|
Loading…
x
Reference in New Issue
Block a user