Skip to content

Commit b074c0f

Browse files
committed
tests for set_interval()
1 parent 3b9590b commit b074c0f

File tree

4 files changed

+161
-22
lines changed

4 files changed

+161
-22
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ REGRESS = pathman_basic \
2626
pathman_permissions \
2727
pathman_rowmarks \
2828
pathman_utility_stmt_hooking \
29-
pathman_calamity
29+
pathman_calamity \
30+
pathman_interval
3031
EXTRA_REGRESS_OPTS=--temp-config=$(top_srcdir)/$(subdir)/conf.add
3132
EXTRA_CLEAN = pg_pathman--$(EXTVERSION).sql ./isolation_output
3233

expected/pathman_interval.out

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
\set VERBOSITY terse
2+
CREATE EXTENSION pg_pathman;
3+
/* Range partitions for INTEGER type */
4+
CREATE TABLE abc (id SERIAL);
5+
SELECT create_range_partitions('abc', 'id', 0, 100, 2);
6+
create_range_partitions
7+
-------------------------
8+
2
9+
(1 row)
10+
11+
SELECT set_interval('abc', NULL::INTEGER);
12+
set_interval
13+
--------------
14+
15+
(1 row)
16+
17+
/* pg_pathman shouldn't be able to create a new partition */
18+
INSERT INTO abc VALUES (250);
19+
ERROR: could not create new partitions for relation "abc"
20+
/* Set a trivial interval */
21+
SELECT set_interval('abc', 0);
22+
ERROR: interval must not be trivial
23+
/* We also shouldn't be able to set a trivial interval directly in pathman_config table */
24+
UPDATE pathman_config SET range_interval = '0' WHERE partrel = 'abc'::REGCLASS;
25+
ERROR: interval must not be trivial
26+
/* Set a normal interval */
27+
SELECT set_interval('abc', 1000);
28+
set_interval
29+
--------------
30+
31+
(1 row)
32+
33+
INSERT INTO abc VALUES (250);
34+
SELECT * FROM pathman_config;
35+
partrel | attname | parttype | range_interval
36+
---------+---------+----------+----------------
37+
abc | id | 2 | 1000
38+
(1 row)
39+
40+
DROP TABLE abc cascade;
41+
NOTICE: drop cascades to 3 other objects
42+
/* Range partitions for DATE type */
43+
CREATE TABLE abc (dt DATE NOT NULL);
44+
SELECT create_range_partitions('abc', 'dt', '2016-01-01'::DATE, '1 day'::INTERVAL, 2);
45+
create_range_partitions
46+
-------------------------
47+
2
48+
(1 row)
49+
50+
SELECT set_interval('abc', NULL::INTERVAL);
51+
set_interval
52+
--------------
53+
54+
(1 row)
55+
56+
/* Set a trivial interval */
57+
SELECT set_interval('abc', '1 second'::INTERVAL);
58+
ERROR: interval must not be trivial
59+
/* Set a normal interval */
60+
SELECT set_interval('abc', '1 month'::INTERVAL);
61+
set_interval
62+
--------------
63+
64+
(1 row)
65+
66+
SELECT * FROM pathman_config;
67+
partrel | attname | parttype | range_interval
68+
---------+---------+----------+----------------
69+
abc | dt | 2 | @ 1 mon
70+
(1 row)
71+
72+
DROP TABLE abc cascade;
73+
NOTICE: drop cascades to 2 other objects
74+
/* Hash partitioned table shouldn't accept any interval value */
75+
CREATE TABLE abc (id SERIAL);
76+
SELECT create_hash_partitions('abc', 'id', 3);
77+
create_hash_partitions
78+
------------------------
79+
3
80+
(1 row)
81+
82+
SELECT set_interval('abc', 100);
83+
ERROR: table "abc" is not partitioned by RANGE
84+
SELECT set_interval('abc', NULL::INTEGER);
85+
ERROR: table "abc" is not partitioned by RANGE
86+
DROP TABLE abc cascade;
87+
NOTICE: drop cascades to 3 other objects
88+
DROP EXTENSION pg_pathman;

sql/pathman_interval.sql

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
\set VERBOSITY terse
2+
CREATE EXTENSION pg_pathman;
3+
4+
/* Range partitions for INTEGER type */
5+
CREATE TABLE abc (id SERIAL);
6+
SELECT create_range_partitions('abc', 'id', 0, 100, 2);
7+
SELECT set_interval('abc', NULL::INTEGER);
8+
/* pg_pathman shouldn't be able to create a new partition */
9+
INSERT INTO abc VALUES (250);
10+
/* Set a trivial interval */
11+
SELECT set_interval('abc', 0);
12+
/* We also shouldn't be able to set a trivial interval directly in pathman_config table */
13+
UPDATE pathman_config SET range_interval = '0' WHERE partrel = 'abc'::REGCLASS;
14+
/* Set a normal interval */
15+
SELECT set_interval('abc', 1000);
16+
INSERT INTO abc VALUES (250);
17+
SELECT * FROM pathman_config;
18+
DROP TABLE abc cascade;
19+
20+
/* Range partitions for DATE type */
21+
CREATE TABLE abc (dt DATE NOT NULL);
22+
SELECT create_range_partitions('abc', 'dt', '2016-01-01'::DATE, '1 day'::INTERVAL, 2);
23+
SELECT set_interval('abc', NULL::INTERVAL);
24+
/* Set a trivial interval */
25+
SELECT set_interval('abc', '1 second'::INTERVAL);
26+
/* Set a normal interval */
27+
SELECT set_interval('abc', '1 month'::INTERVAL);
28+
SELECT * FROM pathman_config;
29+
DROP TABLE abc cascade;
30+
31+
/* Hash partitioned table shouldn't accept any interval value */
32+
CREATE TABLE abc (id SERIAL);
33+
SELECT create_hash_partitions('abc', 'id', 3);
34+
SELECT set_interval('abc', 100);
35+
SELECT set_interval('abc', NULL::INTEGER);
36+
DROP TABLE abc cascade;
37+
38+
DROP EXTENSION pg_pathman;

src/pl_range_funcs.c

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -628,9 +628,6 @@ validate_interval_value(PG_FUNCTION_ARGS)
628628
Datum interval_value;
629629
Oid interval_type;
630630

631-
char *attname_cstr;
632-
Oid atttype; /* type of partitioned attribute */
633-
634631
if (PG_ARGISNULL(0))
635632
elog(ERROR, "'partrel' should not be NULL");
636633

@@ -640,34 +637,43 @@ validate_interval_value(PG_FUNCTION_ARGS)
640637
if (PG_ARGISNULL(2))
641638
elog(ERROR, "'parttype' should not be NULL");
642639

643-
/* it's OK if interval is NULL and table is HASH-partitioned */
644-
if (PG_ARGISNULL(3))
645-
PG_RETURN_BOOL(parttype == PT_HASH);
640+
/*
641+
* NULL interval is fine for both HASH and RANGE. But for RANGE we need
642+
* to make some additional checks
643+
*/
644+
if (!PG_ARGISNULL(3))
645+
{
646+
char *attname_cstr;
647+
Oid atttype; /* type of partitioned attribute */
648+
649+
if (parttype == PT_HASH)
650+
elog(ERROR, "interval must be NULL for HASH partitioned table");
646651

647-
/* Convert attname to CSTRING and fetch column's type */
648-
attname_cstr = text_to_cstring(attname);
649-
atttype = get_attribute_type(partrel, attname_cstr, false);
652+
/* Convert attname to CSTRING and fetch column's type */
653+
attname_cstr = text_to_cstring(attname);
654+
atttype = get_attribute_type(partrel, attname_cstr, false);
650655

651-
/* Try converting textual representation */
652-
interval_value = extract_binary_interval_from_text(interval_text,
653-
atttype,
654-
&interval_type);
656+
/* Try converting textual representation */
657+
interval_value = extract_binary_interval_from_text(interval_text,
658+
atttype,
659+
&interval_type);
655660

656-
/* Check that interval isn't trivial */
657-
if (interval_is_trivial(atttype, interval_value, interval_type))
658-
elog(ERROR, "Interval must not be trivial");
661+
/* Check that interval isn't trivial */
662+
if (interval_is_trivial(atttype, interval_value, interval_type))
663+
elog(ERROR, "interval must not be trivial");
664+
}
659665

660666
PG_RETURN_BOOL(true);
661667
}
662668

663669

664670
/*
665-
* Check that interval is somehow significant to avoid of infinite loops while
666-
* adding new partitions
671+
* Check if interval is insignificant to avoid infinite loops while adding
672+
* new partitions
667673
*
668674
* The main idea behind this function is to add specified interval to some
669-
* default value (zero for numeric types and '1970-01-01' for datetime types)
670-
* and look if it is changed. If it is then return true.
675+
* default value (zero for numeric types and current date/timestamp for datetime
676+
* types) and look if it is changed. If it is then return true.
671677
*/
672678
static bool
673679
interval_is_trivial(Oid atttype, Datum interval, Oid interval_type)
@@ -727,7 +733,13 @@ interval_is_trivial(Oid atttype, Datum interval, Oid interval_type)
727733

728734
/*
729735
* If operator result type isn't the same as original value then
730-
* convert it
736+
* convert it. We need this to make sure that specified interval would
737+
* change the _origianal_ value somehow. For example, if we add one second
738+
* to a date then we'll get a timestamp which is one second later than
739+
* original date (obviously). But when we convert it back to a date we will
740+
* get the same original value meaning that one second interval wouldn't
741+
* change original value anyhow. We should consider such interval
742+
* as trivial
731743
*/
732744
if (op_result_type != atttype)
733745
{

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy