mirror of
https://github.com/postgres/postgres.git
synced 2025-07-05 07:21:24 +03:00
Use the right memory context for partkey's FmgrInfo
We were using CurrentMemoryContext to put the partsupfunc fmgr_info into, which isn't right, because we want the PartitionKey as a whole to be in the isolated Relation->rd_partkeycxt context. This can cause a crash with user-defined support functions in the operator classes used by partitioning keys. (Maybe this can cause problems with core-supplied opclasses too, not sure.) This is demonstrably broken in Postgres 10, too, but the initial proposed fix runs afoul of a problem discussed back when8a0596cb65
("Get rid of copy_partition_key") reorganized that code: namely that it is possible to jump out of RelationBuildPartitionKey because of some error and leave a dangling memory context child of CacheMemoryContext. Also, while reviewing this I noticed that the removed-in-pg11 copy_partition_key was doing something wrong, unfixed in pg10, namely doing memcpy() on the FmgrInfo, which is bogus (should be doing fmgr_info_copy). Therefore, in branch pg10, the sane fix seems to be to backpatch both the aforementioned8a0596cb65
and its followupbe2343221f
("Protect against hypothetical memory leaks in RelationGetPartitionKey"), so do that, then apply the fmgr_info memcxt bugfix on top. Add a test case exercising btree-based custom operator classes, which causes a crash prior to this fix. This is not a security problem, because in order to create an operator class you need superuser privileges anyway. Authors: Álvaro Herrera and Amit Langote Reported and diagnosed by: Amit Langote Discussion: https://postgr.es/m/3041e853-b1dd-a0c6-ff21-7cc5633bffd0@lab.ntt.co.jp
This commit is contained in:
2
src/backend/utils/cache/relcache.c
vendored
2
src/backend/utils/cache/relcache.c
vendored
@ -1034,7 +1034,7 @@ RelationBuildPartitionKey(Relation relation)
|
|||||||
procnum,
|
procnum,
|
||||||
format_type_be(opclassform->opcintype))));
|
format_type_be(opclassform->opcintype))));
|
||||||
|
|
||||||
fmgr_info(funcid, &key->partsupfunc[i]);
|
fmgr_info_cxt(funcid, &key->partsupfunc[i], partkeycxt);
|
||||||
|
|
||||||
/* Collation */
|
/* Collation */
|
||||||
key->partcollation[i] = collation->values[i];
|
key->partcollation[i] = collation->values[i];
|
||||||
|
@ -837,10 +837,22 @@ Partition of: range_parted4 FOR VALUES FROM (6, 8, MINVALUE) TO (9, MAXVALUE, MA
|
|||||||
Partition constraint: ((abs(a) IS NOT NULL) AND (abs(b) IS NOT NULL) AND (c IS NOT NULL) AND ((abs(a) > 6) OR ((abs(a) = 6) AND (abs(b) >= 8))) AND (abs(a) <= 9))
|
Partition constraint: ((abs(a) IS NOT NULL) AND (abs(b) IS NOT NULL) AND (c IS NOT NULL) AND ((abs(a) > 6) OR ((abs(a) = 6) AND (abs(b) >= 8))) AND (abs(a) <= 9))
|
||||||
|
|
||||||
DROP TABLE range_parted4;
|
DROP TABLE range_parted4;
|
||||||
|
-- user-defined operator class in partition key
|
||||||
|
CREATE FUNCTION my_int4_sort(int4,int4) RETURNS int LANGUAGE sql
|
||||||
|
AS $$ SELECT CASE WHEN $1 = $2 THEN 0 WHEN $1 > $2 THEN 1 ELSE -1 END; $$;
|
||||||
|
CREATE OPERATOR CLASS test_int4_ops FOR TYPE int4 USING btree AS
|
||||||
|
OPERATOR 1 < (int4,int4), OPERATOR 2 <= (int4,int4),
|
||||||
|
OPERATOR 3 = (int4,int4), OPERATOR 4 >= (int4,int4),
|
||||||
|
OPERATOR 5 > (int4,int4), FUNCTION 1 my_int4_sort(int4,int4);
|
||||||
|
CREATE TABLE partkey_t (a int4) PARTITION BY RANGE (a test_int4_ops);
|
||||||
|
CREATE TABLE partkey_t_1 PARTITION OF partkey_t FOR VALUES FROM (0) TO (1000);
|
||||||
|
INSERT INTO partkey_t VALUES (100);
|
||||||
|
INSERT INTO partkey_t VALUES (200);
|
||||||
-- cleanup
|
-- cleanup
|
||||||
DROP TABLE parted, list_parted, range_parted, list_parted2, range_parted2, range_parted3;
|
DROP TABLE parted, list_parted, range_parted, list_parted2, range_parted2, range_parted3;
|
||||||
DROP TABLE hash_parted;
|
DROP TABLE partkey_t, hash_parted, hash_parted2;
|
||||||
DROP TABLE hash_parted2;
|
DROP OPERATOR CLASS test_int4_ops USING btree;
|
||||||
|
DROP FUNCTION my_int4_sort(int4,int4);
|
||||||
-- comments on partitioned tables columns
|
-- comments on partitioned tables columns
|
||||||
CREATE TABLE parted_col_comment (a int, b text) PARTITION BY LIST (a);
|
CREATE TABLE parted_col_comment (a int, b text) PARTITION BY LIST (a);
|
||||||
COMMENT ON TABLE parted_col_comment IS 'Am partitioned table';
|
COMMENT ON TABLE parted_col_comment IS 'Am partitioned table';
|
||||||
|
@ -688,10 +688,23 @@ CREATE TABLE range_parted4_3 PARTITION OF range_parted4 FOR VALUES FROM (6, 8, M
|
|||||||
\d+ range_parted4_3
|
\d+ range_parted4_3
|
||||||
DROP TABLE range_parted4;
|
DROP TABLE range_parted4;
|
||||||
|
|
||||||
|
-- user-defined operator class in partition key
|
||||||
|
CREATE FUNCTION my_int4_sort(int4,int4) RETURNS int LANGUAGE sql
|
||||||
|
AS $$ SELECT CASE WHEN $1 = $2 THEN 0 WHEN $1 > $2 THEN 1 ELSE -1 END; $$;
|
||||||
|
CREATE OPERATOR CLASS test_int4_ops FOR TYPE int4 USING btree AS
|
||||||
|
OPERATOR 1 < (int4,int4), OPERATOR 2 <= (int4,int4),
|
||||||
|
OPERATOR 3 = (int4,int4), OPERATOR 4 >= (int4,int4),
|
||||||
|
OPERATOR 5 > (int4,int4), FUNCTION 1 my_int4_sort(int4,int4);
|
||||||
|
CREATE TABLE partkey_t (a int4) PARTITION BY RANGE (a test_int4_ops);
|
||||||
|
CREATE TABLE partkey_t_1 PARTITION OF partkey_t FOR VALUES FROM (0) TO (1000);
|
||||||
|
INSERT INTO partkey_t VALUES (100);
|
||||||
|
INSERT INTO partkey_t VALUES (200);
|
||||||
|
|
||||||
-- cleanup
|
-- cleanup
|
||||||
DROP TABLE parted, list_parted, range_parted, list_parted2, range_parted2, range_parted3;
|
DROP TABLE parted, list_parted, range_parted, list_parted2, range_parted2, range_parted3;
|
||||||
DROP TABLE hash_parted;
|
DROP TABLE partkey_t, hash_parted, hash_parted2;
|
||||||
DROP TABLE hash_parted2;
|
DROP OPERATOR CLASS test_int4_ops USING btree;
|
||||||
|
DROP FUNCTION my_int4_sort(int4,int4);
|
||||||
|
|
||||||
-- comments on partitioned tables columns
|
-- comments on partitioned tables columns
|
||||||
CREATE TABLE parted_col_comment (a int, b text) PARTITION BY LIST (a);
|
CREATE TABLE parted_col_comment (a int, b text) PARTITION BY LIST (a);
|
||||||
|
Reference in New Issue
Block a user