timescaledb/test/expected/create_hypertable.out
gayyappan 2702140fa3 Cannot add dimension if table has empty chunks
add_dimension should fail when table has no
data but still has empty chunks.
Fixes #1623
2020-02-10 10:47:23 -05:00

647 lines
34 KiB
Plaintext

-- This file and its contents are licensed under the Apache License 2.0.
-- Please see the included NOTICE for copyright information and
-- LICENSE-APACHE for a copy of the license.
\c :TEST_DBNAME :ROLE_SUPERUSER
create schema test_schema AUTHORIZATION :ROLE_DEFAULT_PERM_USER;
create schema chunk_schema AUTHORIZATION :ROLE_DEFAULT_PERM_USER_2;
SET ROLE :ROLE_DEFAULT_PERM_USER;
create table test_schema.test_table(time BIGINT, temp float8, device_id text, device_type text, location text, id int, id2 int);
\set ON_ERROR_STOP 0
-- get_create_command should fail since hypertable isn't made yet
SELECT * FROM _timescaledb_internal.get_create_command('test_table');
ERROR: hypertable "test_table" not found
\set ON_ERROR_STOP 1
\dt "test_schema".*
List of relations
Schema | Name | Type | Owner
-------------+------------+-------+-------------------
test_schema | test_table | table | default_perm_user
(1 row)
create table test_schema.test_table_no_not_null(time BIGINT, device_id text);
\set ON_ERROR_STOP 0
-- Permission denied with unprivileged role
SET ROLE :ROLE_DEFAULT_PERM_USER_2;
select * from create_hypertable('test_schema.test_table_no_not_null', 'time', 'device_id', 2, chunk_time_interval=>_timescaledb_internal.interval_to_usec('1 month'));
ERROR: permission denied for schema test_schema at character 33
-- CREATE on schema is not enough
SET ROLE :ROLE_DEFAULT_PERM_USER;
GRANT ALL ON SCHEMA test_schema TO :ROLE_DEFAULT_PERM_USER_2;
SET ROLE :ROLE_DEFAULT_PERM_USER_2;
select * from create_hypertable('test_schema.test_table_no_not_null', 'time', 'device_id', 2, chunk_time_interval=>_timescaledb_internal.interval_to_usec('1 month'));
ERROR: must be owner of hypertable "test_table_no_not_null"
\set ON_ERROR_STOP 1
-- Should work with when granted table owner role
RESET ROLE;
GRANT :ROLE_DEFAULT_PERM_USER TO :ROLE_DEFAULT_PERM_USER_2;
SET ROLE :ROLE_DEFAULT_PERM_USER_2;
select * from create_hypertable('test_schema.test_table_no_not_null', 'time', 'device_id', 2, chunk_time_interval=>_timescaledb_internal.interval_to_usec('1 month'));
NOTICE: adding not-null constraint to column "time"
hypertable_id | schema_name | table_name | created
---------------+-------------+------------------------+---------
1 | test_schema | test_table_no_not_null | t
(1 row)
\set ON_ERROR_STOP 0
insert into test_schema.test_table_no_not_null (device_id) VALUES('foo');
ERROR: NULL value in column "time" violates not-null constraint
\set ON_ERROR_STOP 1
insert into test_schema.test_table_no_not_null (time, device_id) VALUES(1, 'foo');
RESET ROLE;
SET ROLE :ROLE_DEFAULT_PERM_USER;
\set ON_ERROR_STOP 0
-- No permissions on associated schema should fail
select * from create_hypertable('test_schema.test_table', 'time', 'device_id', 2, chunk_time_interval=>_timescaledb_internal.interval_to_usec('1 month'), associated_schema_name => 'chunk_schema');
ERROR: permissions denied: cannot create chunks in schema "chunk_schema"
\set ON_ERROR_STOP 1
-- Granting permissions on chunk_schema should make things work
RESET ROLE;
GRANT CREATE ON SCHEMA chunk_schema TO :ROLE_DEFAULT_PERM_USER;
SET ROLE :ROLE_DEFAULT_PERM_USER;
select * from create_hypertable('test_schema.test_table', 'time', 'device_id', 2, chunk_time_interval=>_timescaledb_internal.interval_to_usec('1 month'), associated_schema_name => 'chunk_schema');
NOTICE: adding not-null constraint to column "time"
hypertable_id | schema_name | table_name | created
---------------+-------------+------------+---------
2 | test_schema | test_table | t
(1 row)
-- Check that the insert block trigger exists
SELECT * FROM test.show_triggers('test_schema.test_table');
Trigger | Type | Function | Definition
-------------------+------+--------------------------------------+----------------------------------------------------------------------------------------------------------------------------------
ts_insert_blocker | 7 | _timescaledb_internal.insert_blocker | ts_insert_blocker BEFORE INSERT ON test_schema.test_table FOR EACH ROW EXECUTE PROCEDURE _timescaledb_internal.insert_blocker()
(1 row)
SELECT * FROM _timescaledb_internal.get_create_command('test_table');
get_create_command
--------------------------------------------------------------------------------------------------------------------------------------------------
SELECT create_hypertable('test_schema.test_table', 'time', 'device_id', 2, chunk_time_interval => 2592000000000, create_default_indexes=>FALSE);
(1 row)
--test adding one more closed dimension
select add_dimension('test_schema.test_table', 'location', 4);
add_dimension
---------------------------------------
(5,test_schema,test_table,location,t)
(1 row)
select * from _timescaledb_catalog.hypertable where table_name = 'test_table';
id | schema_name | table_name | associated_schema_name | associated_table_prefix | num_dimensions | chunk_sizing_func_schema | chunk_sizing_func_name | chunk_target_size | compressed | compressed_hypertable_id
----+-------------+------------+------------------------+-------------------------+----------------+--------------------------+--------------------------+-------------------+------------+--------------------------
2 | test_schema | test_table | chunk_schema | _hyper_2 | 3 | _timescaledb_internal | calculate_chunk_interval | 0 | f |
(1 row)
select * from _timescaledb_catalog.dimension;
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | integer_now_func_schema | integer_now_func
----+---------------+-------------+-------------+---------+------------+--------------------------+--------------------+-----------------+-------------------------+------------------
1 | 1 | time | bigint | t | | | | 2592000000000 | |
2 | 1 | device_id | text | f | 2 | _timescaledb_internal | get_partition_hash | | |
3 | 2 | time | bigint | t | | | | 2592000000000 | |
4 | 2 | device_id | text | f | 2 | _timescaledb_internal | get_partition_hash | | |
5 | 2 | location | text | f | 4 | _timescaledb_internal | get_partition_hash | | |
(5 rows)
--test that we can change the number of partitions and that 1 is allowed
SELECT set_number_partitions('test_schema.test_table', 1, 'location');
set_number_partitions
-----------------------
(1 row)
select * from _timescaledb_catalog.dimension WHERE column_name = 'location';
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | integer_now_func_schema | integer_now_func
----+---------------+-------------+-------------+---------+------------+--------------------------+--------------------+-----------------+-------------------------+------------------
5 | 2 | location | text | f | 1 | _timescaledb_internal | get_partition_hash | | |
(1 row)
SELECT set_number_partitions('test_schema.test_table', 2, 'location');
set_number_partitions
-----------------------
(1 row)
select * from _timescaledb_catalog.dimension WHERE column_name = 'location';
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | integer_now_func_schema | integer_now_func
----+---------------+-------------+-------------+---------+------------+--------------------------+--------------------+-----------------+-------------------------+------------------
5 | 2 | location | text | f | 2 | _timescaledb_internal | get_partition_hash | | |
(1 row)
\set ON_ERROR_STOP 0
--must give an explicit dimension when there are multiple space dimensions
SELECT set_number_partitions('test_schema.test_table', 3);
ERROR: hypertable "test_table" has multiple space dimensions
--too few
SELECT set_number_partitions('test_schema.test_table', 0, 'location');
ERROR: invalid number of partitions: must be between 1 and 32767
-- Too many
SELECT set_number_partitions('test_schema.test_table', 32768, 'location');
ERROR: invalid number of partitions: must be between 1 and 32767
-- get_create_command only works on tables w/ 1 or 2 dimensions
SELECT * FROM _timescaledb_internal.get_create_command('test_table');
ERROR: get_create_command only supports hypertables with up to 2 dimensions
\set ON_ERROR_STOP 1
--test adding one more open dimension
select add_dimension('test_schema.test_table', 'id', chunk_time_interval => 1000);
NOTICE: adding not-null constraint to column "id"
add_dimension
---------------------------------
(6,test_schema,test_table,id,t)
(1 row)
select * from _timescaledb_catalog.hypertable where table_name = 'test_table';
id | schema_name | table_name | associated_schema_name | associated_table_prefix | num_dimensions | chunk_sizing_func_schema | chunk_sizing_func_name | chunk_target_size | compressed | compressed_hypertable_id
----+-------------+------------+------------------------+-------------------------+----------------+--------------------------+--------------------------+-------------------+------------+--------------------------
2 | test_schema | test_table | chunk_schema | _hyper_2 | 4 | _timescaledb_internal | calculate_chunk_interval | 0 | f |
(1 row)
select * from _timescaledb_catalog.dimension;
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | integer_now_func_schema | integer_now_func
----+---------------+-------------+-------------+---------+------------+--------------------------+--------------------+-----------------+-------------------------+------------------
1 | 1 | time | bigint | t | | | | 2592000000000 | |
2 | 1 | device_id | text | f | 2 | _timescaledb_internal | get_partition_hash | | |
3 | 2 | time | bigint | t | | | | 2592000000000 | |
4 | 2 | device_id | text | f | 2 | _timescaledb_internal | get_partition_hash | | |
5 | 2 | location | text | f | 2 | _timescaledb_internal | get_partition_hash | | |
6 | 2 | id | integer | t | | | | 1000 | |
(6 rows)
-- Test add_dimension: can use interval types for TIMESTAMPTZ columns
CREATE TABLE dim_test_time(time TIMESTAMPTZ, time2 TIMESTAMPTZ, time3 BIGINT, temp float8, device int, location int);
SELECT create_hypertable('dim_test_time', 'time');
NOTICE: adding not-null constraint to column "time"
create_hypertable
----------------------------
(3,public,dim_test_time,t)
(1 row)
SELECT add_dimension('dim_test_time', 'time2', chunk_time_interval => INTERVAL '1 day');
NOTICE: adding not-null constraint to column "time2"
add_dimension
----------------------------------
(8,public,dim_test_time,time2,t)
(1 row)
-- Test add_dimension: only integral should work on BIGINT columns
\set ON_ERROR_STOP 0
SELECT add_dimension('dim_test_time', 'time3', chunk_time_interval => INTERVAL '1 day');
ERROR: invalid interval: must be an integer type for integer dimensions
-- string is not a valid type
SELECT add_dimension('dim_test_time', 'time3', chunk_time_interval => 'foo'::TEXT);
ERROR: invalid interval: must be an interval or integer type
\set ON_ERROR_STOP 1
SELECT add_dimension('dim_test_time', 'time3', chunk_time_interval => 500);
NOTICE: adding not-null constraint to column "time3"
add_dimension
----------------------------------
(9,public,dim_test_time,time3,t)
(1 row)
-- Test add_dimension: integrals should work on TIMESTAMPTZ columns
CREATE TABLE dim_test_time2(time TIMESTAMPTZ, time2 TIMESTAMPTZ, temp float8, device int, location int);
SELECT create_hypertable('dim_test_time2', 'time');
NOTICE: adding not-null constraint to column "time"
create_hypertable
-----------------------------
(4,public,dim_test_time2,t)
(1 row)
SELECT add_dimension('dim_test_time2', 'time2', chunk_time_interval => 500);
WARNING: unexpected interval: smaller than one second
NOTICE: adding not-null constraint to column "time2"
add_dimension
------------------------------------
(11,public,dim_test_time2,time2,t)
(1 row)
--adding a dimension twice should not fail with 'if_not_exists'
SELECT add_dimension('dim_test_time2', 'time2', chunk_time_interval => 500, if_not_exists => true);
NOTICE: column "time2" is already a dimension, skipping
add_dimension
------------------------------------
(11,public,dim_test_time2,time2,f)
(1 row)
\set ON_ERROR_STOP 0
--adding on a non-hypertable
CREATE TABLE not_hypertable(time TIMESTAMPTZ, temp float8, device int, location int);
SELECT add_dimension('not_hypertable', 'time', chunk_time_interval => 500);
ERROR: table "not_hypertable" is not a hypertable
--adding a non-exist column
SELECT add_dimension('test_schema.test_table', 'nope', 2);
ERROR: column "nope" does not exist
--adding the same dimension twice should fail
select add_dimension('test_schema.test_table', 'location', 2);
ERROR: column "location" is already a dimension
--adding dimension with both number_partitions and chunk_time_interval should fail
select add_dimension('test_schema.test_table', 'id2', number_partitions => 2, chunk_time_interval => 1000);
ERROR: cannot specify both the number of partitions and an interval
--adding a new dimension on a non-empty table should also fail
insert into test_schema.test_table values (123456789, 23.8, 'blue', 'type1', 'nyc', 1, 1);
select add_dimension('test_schema.test_table', 'device_type', 2);
ERROR: hypertable "test_table" has tuples or empty chunks
-- should fail on non-empty table with 'if_not_exists' in case the dimension does not exists
select add_dimension('test_schema.test_table', 'device_type', 2, if_not_exists => true);
ERROR: hypertable "test_table" has tuples or empty chunks
\set ON_ERROR_STOP 1
-- should not fail on non-empty table with 'if_not_exists' in case the dimension exists
select add_dimension('test_schema.test_table', 'location', 2, if_not_exists => true);
NOTICE: column "location" is already a dimension, skipping
add_dimension
---------------------------------------
(5,test_schema,test_table,location,f)
(1 row)
--should fail on empty table that still has chunks --
\set ON_ERROR_STOP 0
delete from test_schema.test_table where time is not null;
select count(*) from test_schema.test_table;
count
-------
0
(1 row)
select add_dimension('test_schema.test_table', 'device_type', 2);
ERROR: hypertable "test_table" has tuples or empty chunks
\set ON_ERROR_STOP 1
--show chunks in the associated schema
\dt "chunk_schema".*
List of relations
Schema | Name | Type | Owner
--------------+------------------+-------+-------------------
chunk_schema | _hyper_2_2_chunk | table | default_perm_user
(1 row)
--test partitioning in only time dimension
create table test_schema.test_1dim(time timestamp, temp float);
select create_hypertable('test_schema.test_1dim', 'time');
NOTICE: adding not-null constraint to column "time"
create_hypertable
-----------------------------
(5,test_schema,test_1dim,t)
(1 row)
SELECT * FROM _timescaledb_internal.get_create_command('test_1dim');
get_create_command
--------------------------------------------------------------------------------------------------------------------------------
SELECT create_hypertable('test_schema.test_1dim', 'time', chunk_time_interval => 604800000000, create_default_indexes=>FALSE);
(1 row)
\dt "test_schema".*
List of relations
Schema | Name | Type | Owner
-------------+------------------------+-------+-------------------
test_schema | test_1dim | table | default_perm_user
test_schema | test_table | table | default_perm_user
test_schema | test_table_no_not_null | table | default_perm_user
(3 rows)
select create_hypertable('test_schema.test_1dim', 'time', if_not_exists => true);
NOTICE: table "test_1dim" is already a hypertable, skipping
create_hypertable
-----------------------------
(5,test_schema,test_1dim,f)
(1 row)
-- Should error when creating again without if_not_exists set to true
\set ON_ERROR_STOP 0
select create_hypertable('test_schema.test_1dim', 'time');
ERROR: table "test_1dim" is already a hypertable
\set ON_ERROR_STOP 1
-- if_not_exist should also work with data in the hypertable
insert into test_schema.test_1dim VALUES ('2004-10-19 10:23:54+02', 1.0);
select create_hypertable('test_schema.test_1dim', 'time', if_not_exists => true);
NOTICE: table "test_1dim" is already a hypertable, skipping
create_hypertable
-----------------------------
(5,test_schema,test_1dim,f)
(1 row)
-- Should error when creating again without if_not_exists set to true
\set ON_ERROR_STOP 0
select create_hypertable('test_schema.test_1dim', 'time');
ERROR: table "test_1dim" is already a hypertable
\set ON_ERROR_STOP 1
-- Test partitioning functions
CREATE OR REPLACE FUNCTION invalid_partfunc(source integer)
RETURNS INTEGER LANGUAGE PLPGSQL IMMUTABLE AS
$BODY$
BEGIN
RETURN NULL;
END
$BODY$;
CREATE OR REPLACE FUNCTION time_partfunc(source text)
RETURNS TIMESTAMPTZ LANGUAGE PLPGSQL IMMUTABLE AS
$BODY$
BEGIN
RETURN timezone('UTC', to_timestamp(source));
END
$BODY$;
CREATE TABLE test_schema.test_invalid_func(time timestamptz, temp float8, device text);
\set ON_ERROR_STOP 0
-- should fail due to invalid signature
SELECT create_hypertable('test_schema.test_invalid_func', 'time', 'device', 2, partitioning_func => 'invalid_partfunc');
ERROR: invalid partitioning function
SELECT create_hypertable('test_schema.test_invalid_func', 'time');
NOTICE: adding not-null constraint to column "time"
create_hypertable
-------------------------------------
(6,test_schema,test_invalid_func,t)
(1 row)
-- should also fail due to invalid signature
SELECT add_dimension('test_schema.test_invalid_func', 'device', 2, partitioning_func => 'invalid_partfunc');
ERROR: invalid partitioning function
\set ON_ERROR_STOP 1
-- Test open-dimension function
CREATE TABLE test_schema.open_dim_part_func(time text, temp float8, device text, event_time text);
\set ON_ERROR_STOP 0
-- should fail due to invalid signature
SELECT create_hypertable('test_schema.open_dim_part_func', 'time', time_partitioning_func => 'invalid_partfunc');
ERROR: invalid partitioning function
\set ON_ERROR_STOP 1
SELECT create_hypertable('test_schema.open_dim_part_func', 'time', time_partitioning_func => 'time_partfunc');
NOTICE: adding not-null constraint to column "time"
create_hypertable
--------------------------------------
(7,test_schema,open_dim_part_func,t)
(1 row)
\set ON_ERROR_STOP 0
-- should fail due to invalid signature
SELECT add_dimension('test_schema.open_dim_part_func', 'event_time', chunk_time_interval => interval '1 day', partitioning_func => 'invalid_partfunc');
ERROR: invalid partitioning function
\set ON_ERROR_STOP 1
SELECT add_dimension('test_schema.open_dim_part_func', 'event_time', chunk_time_interval => interval '1 day', partitioning_func => 'time_partfunc');
NOTICE: adding not-null constraint to column "event_time"
add_dimension
--------------------------------------------------
(15,test_schema,open_dim_part_func,event_time,t)
(1 row)
--test data migration
create table test_schema.test_migrate(time timestamp, temp float);
insert into test_schema.test_migrate VALUES ('2004-10-19 10:23:54+02', 1.0), ('2004-12-19 10:23:54+02', 2.0);
select * from only test_schema.test_migrate;
time | temp
--------------------------+------
Tue Oct 19 10:23:54 2004 | 1
Sun Dec 19 10:23:54 2004 | 2
(2 rows)
\set ON_ERROR_STOP 0
--should fail without migrate_data => true
select create_hypertable('test_schema.test_migrate', 'time');
ERROR: table "test_migrate" is not empty
\set ON_ERROR_STOP 1
select create_hypertable('test_schema.test_migrate', 'time', migrate_data => true);
NOTICE: adding not-null constraint to column "time"
NOTICE: migrating data to chunks
create_hypertable
--------------------------------
(8,test_schema,test_migrate,t)
(1 row)
--there should be two new chunks
select * from _timescaledb_catalog.hypertable where table_name = 'test_migrate';
id | schema_name | table_name | associated_schema_name | associated_table_prefix | num_dimensions | chunk_sizing_func_schema | chunk_sizing_func_name | chunk_target_size | compressed | compressed_hypertable_id
----+-------------+--------------+------------------------+-------------------------+----------------+--------------------------+--------------------------+-------------------+------------+--------------------------
8 | test_schema | test_migrate | _timescaledb_internal | _hyper_8 | 1 | _timescaledb_internal | calculate_chunk_interval | 0 | f |
(1 row)
select * from _timescaledb_catalog.chunk;
id | hypertable_id | schema_name | table_name | compressed_chunk_id | dropped
----+---------------+-----------------------+------------------+---------------------+---------
1 | 1 | _timescaledb_internal | _hyper_1_1_chunk | | f
2 | 2 | chunk_schema | _hyper_2_2_chunk | | f
3 | 5 | _timescaledb_internal | _hyper_5_3_chunk | | f
4 | 8 | _timescaledb_internal | _hyper_8_4_chunk | | f
5 | 8 | _timescaledb_internal | _hyper_8_5_chunk | | f
(5 rows)
select * from test_schema.test_migrate;
time | temp
--------------------------+------
Tue Oct 19 10:23:54 2004 | 1
Sun Dec 19 10:23:54 2004 | 2
(2 rows)
--main table should now be empty
select * from only test_schema.test_migrate;
time | temp
------+------
(0 rows)
select * from only _timescaledb_internal._hyper_8_4_chunk;
time | temp
--------------------------+------
Tue Oct 19 10:23:54 2004 | 1
(1 row)
select * from only _timescaledb_internal._hyper_8_5_chunk;
time | temp
--------------------------+------
Sun Dec 19 10:23:54 2004 | 2
(1 row)
create table test_schema.test_migrate_empty(time timestamp, temp float);
select create_hypertable('test_schema.test_migrate_empty', 'time', migrate_data => true);
NOTICE: adding not-null constraint to column "time"
create_hypertable
--------------------------------------
(9,test_schema,test_migrate_empty,t)
(1 row)
CREATE TYPE test_type AS (time timestamp, temp float);
CREATE TABLE test_table_of_type OF test_type;
SELECT create_hypertable('test_table_of_type', 'time');
NOTICE: adding not-null constraint to column "time"
create_hypertable
----------------------------------
(10,public,test_table_of_type,t)
(1 row)
INSERT INTO test_table_of_type VALUES ('2004-10-19 10:23:54+02', 1.0), ('2004-12-19 10:23:54+02', 2.0);
\set ON_ERROR_STOP 0
DROP TYPE test_type;
ERROR: cannot drop type test_type because other objects depend on it
\set ON_ERROR_STOP 1
DROP TYPE test_type CASCADE;
NOTICE: drop cascades to 3 other objects
CREATE TABLE test_table_of_type (time timestamp, temp float);
SELECT create_hypertable('test_table_of_type', 'time');
NOTICE: adding not-null constraint to column "time"
create_hypertable
----------------------------------
(11,public,test_table_of_type,t)
(1 row)
INSERT INTO test_table_of_type VALUES ('2004-10-19 10:23:54+02', 1.0), ('2004-12-19 10:23:54+02', 2.0);
CREATE TYPE test_type AS (time timestamp, temp float);
ALTER TABLE test_table_of_type OF test_type;
\set ON_ERROR_STOP 0
DROP TYPE test_type;
ERROR: cannot drop type test_type because other objects depend on it
\set ON_ERROR_STOP 1
BEGIN;
DROP TYPE test_type CASCADE;
NOTICE: drop cascades to 3 other objects
ROLLBACK;
ALTER TABLE test_table_of_type NOT OF;
DROP TYPE test_type;
-- Reset GRANTS
\c :TEST_DBNAME :ROLE_SUPERUSER
REVOKE :ROLE_DEFAULT_PERM_USER FROM :ROLE_DEFAULT_PERM_USER_2;
-- Test custom partitioning functions
CREATE OR REPLACE FUNCTION partfunc_not_immutable(source anyelement)
RETURNS INTEGER LANGUAGE PLPGSQL AS
$BODY$
BEGIN
RETURN _timescaledb_internal.get_partition_hash(source);
END
$BODY$;
CREATE OR REPLACE FUNCTION partfunc_bad_return_type(source anyelement)
RETURNS BIGINT LANGUAGE PLPGSQL IMMUTABLE AS
$BODY$
BEGIN
RETURN _timescaledb_internal.get_partition_hash(source);
END
$BODY$;
CREATE OR REPLACE FUNCTION partfunc_bad_arg_type(source text)
RETURNS INTEGER LANGUAGE PLPGSQL IMMUTABLE AS
$BODY$
BEGIN
RETURN _timescaledb_internal.get_partition_hash(source);
END
$BODY$;
CREATE OR REPLACE FUNCTION partfunc_bad_multi_arg(source anyelement, extra_arg integer)
RETURNS INTEGER LANGUAGE PLPGSQL IMMUTABLE AS
$BODY$
BEGIN
RETURN _timescaledb_internal.get_partition_hash(source);
END
$BODY$;
CREATE OR REPLACE FUNCTION partfunc_valid(source anyelement)
RETURNS INTEGER LANGUAGE PLPGSQL IMMUTABLE AS
$BODY$
BEGIN
RETURN _timescaledb_internal.get_partition_hash(source);
END
$BODY$;
create table test_schema.test_partfunc(time timestamptz, temp float, device int);
-- Test that create_hypertable fails due to invalid partitioning function
\set ON_ERROR_STOP 0
select create_hypertable('test_schema.test_partfunc', 'time', 'device', 2, partitioning_func => 'partfunc_not_immutable');
ERROR: invalid partitioning function
select create_hypertable('test_schema.test_partfunc', 'time', 'device', 2, partitioning_func => 'partfunc_bad_return_type');
ERROR: invalid partitioning function
select create_hypertable('test_schema.test_partfunc', 'time', 'device', 2, partitioning_func => 'partfunc_bad_arg_type');
ERROR: invalid partitioning function
select create_hypertable('test_schema.test_partfunc', 'time', 'device', 2, partitioning_func => 'partfunc_bad_multi_arg');
ERROR: invalid partitioning function
\set ON_ERROR_STOP 1
-- Test that add_dimension fails due to invalid partitioning function
select create_hypertable('test_schema.test_partfunc', 'time');
NOTICE: adding not-null constraint to column "time"
create_hypertable
----------------------------------
(12,test_schema,test_partfunc,t)
(1 row)
\set ON_ERROR_STOP 0
select add_dimension('test_schema.test_partfunc', 'device', 2, partitioning_func => 'partfunc_not_immutable');
ERROR: invalid partitioning function
select add_dimension('test_schema.test_partfunc', 'device', 2, partitioning_func => 'partfunc_bad_return_type');
ERROR: invalid partitioning function
select add_dimension('test_schema.test_partfunc', 'device', 2, partitioning_func => 'partfunc_bad_arg_type');
ERROR: invalid partitioning function
select add_dimension('test_schema.test_partfunc', 'device', 2, partitioning_func => 'partfunc_bad_multi_arg');
ERROR: invalid partitioning function
\set ON_ERROR_STOP 1
-- A valid function should work:
select add_dimension('test_schema.test_partfunc', 'device', 2, partitioning_func => 'partfunc_valid');
add_dimension
-----------------------------------------
(21,test_schema,test_partfunc,device,t)
(1 row)
-- check get_create_command produces valid command
CREATE TABLE test_schema.test_sql_cmd(time TIMESTAMPTZ, temp FLOAT8, device_id TEXT, device_type TEXT, location TEXT, id INT, id2 INT);
SELECT create_hypertable('test_schema.test_sql_cmd','time');
NOTICE: adding not-null constraint to column "time"
create_hypertable
---------------------------------
(13,test_schema,test_sql_cmd,t)
(1 row)
SELECT * FROM _timescaledb_internal.get_create_command('test_sql_cmd');
get_create_command
-----------------------------------------------------------------------------------------------------------------------------------
SELECT create_hypertable('test_schema.test_sql_cmd', 'time', chunk_time_interval => 604800000000, create_default_indexes=>FALSE);
(1 row)
SELECT _timescaledb_internal.get_create_command('test_sql_cmd') AS create_cmd; \gset
create_cmd
-----------------------------------------------------------------------------------------------------------------------------------
SELECT create_hypertable('test_schema.test_sql_cmd', 'time', chunk_time_interval => 604800000000, create_default_indexes=>FALSE);
(1 row)
DROP TABLE test_schema.test_sql_cmd CASCADE;
CREATE TABLE test_schema.test_sql_cmd(time TIMESTAMPTZ, temp FLOAT8, device_id TEXT, device_type TEXT, location TEXT, id INT, id2 INT);
SELECT test.execute_sql(:'create_cmd');
NOTICE: adding not-null constraint to column "time"
execute_sql
-----------------------------------------------------------------------------------------------------------------------------------
SELECT create_hypertable('test_schema.test_sql_cmd', 'time', chunk_time_interval => 604800000000, create_default_indexes=>FALSE);
(1 row)
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
CREATE TABLE test_table_int(time bigint, junk int);
SELECT hypertable_id AS "TEST_TABLE_INT_HYPERTABLE_ID" FROM create_hypertable('test_table_int', 'time', chunk_time_interval => 1) \gset
NOTICE: adding not-null constraint to column "time"
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE SCHEMA IF NOT EXISTS my_schema;
create or replace function my_schema.dummy_now2() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 1::BIGINT';
grant execute on ALL FUNCTIONS IN SCHEMA my_schema to public;
create or replace function dummy_now3() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 1::BIGINT';
grant execute on ALL FUNCTIONS IN SCHEMA my_schema to public;
REVOKE execute ON function dummy_now3() FROM PUBLIC;
CREATE SCHEMA IF NOT EXISTS my_user_schema;
GRANT ALL ON SCHEMA my_user_schema to PUBLIC;
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
create or replace function dummy_now() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 1::BIGINT';
create or replace function my_user_schema.dummy_now4() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 1::BIGINT';
select set_integer_now_func('test_table_int', 'dummy_now');
set_integer_now_func
----------------------
(1 row)
select * from _timescaledb_catalog.dimension WHERE hypertable_id = :TEST_TABLE_INT_HYPERTABLE_ID;
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | integer_now_func_schema | integer_now_func
----+---------------+-------------+-------------+---------+------------+--------------------------+-------------------+-----------------+-------------------------+------------------
24 | 15 | time | bigint | t | | | | 1 | public | dummy_now
(1 row)
\set ON_ERROR_STOP 0
select set_integer_now_func('test_table_int', 'dummy_now');
ERROR: integer_now_func is already set for hypertable "test_table_int"
select set_integer_now_func('test_table_int', 'my_schema.dummy_now2', replace_if_exists => TRUE);
ERROR: permission denied for schema my_schema at character 47
select set_integer_now_func('test_table_int', 'dummy_now3', replace_if_exists => TRUE);
ERROR: permission denied for function dummy_now3
\set ON_ERROR_STOP
select set_integer_now_func('test_table_int', 'my_user_schema.dummy_now4', replace_if_exists => TRUE);
set_integer_now_func
----------------------
(1 row)
\c :TEST_DBNAME :ROLE_SUPERUSER
ALTER SCHEMA my_user_schema RENAME TO my_new_schema;
select * from _timescaledb_catalog.dimension WHERE hypertable_id = :TEST_TABLE_INT_HYPERTABLE_ID;
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | integer_now_func_schema | integer_now_func
----+---------------+-------------+-------------+---------+------------+--------------------------+-------------------+-----------------+-------------------------+------------------
24 | 15 | time | bigint | t | | | | 1 | my_new_schema | dummy_now4
(1 row)