提交 079ca994 编写于 作者: A Adam Berlin 提交者: Sambitesh Dash

Avoid PANIC on multiple function execution when using ORCA

A cached query planned statement contains information that is
freed after the first execution of a function. The second execution
used the cached planned statement to populate the execution state
using a freed pointer and throws a segmentation fault.

To resolve, we do not free the dynamicTableScanInfo.
Co-authored-by: NDavid Kimura <dkimura@pivotal.io>
Co-authored-by: NTaylor Vesely <tvesely@pivotal.io>
(cherry picked from commit 04e43e64)
上级 f8b2634a
......@@ -202,28 +202,6 @@ CreateExecutorState(void)
return estate;
}
/*
* freeDynamicTableScanInfo
* Free the space for DynamicTableScanInfo.
*/
static void
freeDynamicTableScanInfo(DynamicTableScanInfo *scanInfo)
{
Assert(scanInfo != NULL);
if (scanInfo->partsMetadata != NIL)
{
list_free_deep(scanInfo->partsMetadata);
}
if (scanInfo->numSelectorsPerScanId != NIL)
{
list_free(scanInfo->numSelectorsPerScanId);
}
pfree(scanInfo);
}
/* ----------------
* FreeExecutorState
*
......@@ -268,14 +246,7 @@ FreeExecutorState(EState *estate)
estate->dispatcherState = NULL;
}
/*
* Free dynamicTableScanInfo.
*/
if (estate->dynamicTableScanInfo != NULL)
{
freeDynamicTableScanInfo(estate->dynamicTableScanInfo);
estate->dynamicTableScanInfo = NULL;
}
estate->dynamicTableScanInfo = NULL;
/*
* Greenplum: release partition-related resources (esp. TupleDesc ref counts).
......
CREATE SCHEMA partition_with_user_defined_function;
-- Given there is a partitioned table
create table partition_with_user_defined_function.some_partitioned_table
(
a integer
)
partition by range (a) (
partition b start (0)
);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Greenplum Database data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
NOTICE: CREATE TABLE will create partition "some_partitioned_table_1_prt_b" for table "some_partitioned_table"
-- And a function that queried the partitioned table
CREATE OR REPLACE FUNCTION partition_with_user_defined_function.query_a_partition_table() RETURNS VOID AS
$$
BEGIN
PERFORM * FROM partition_with_user_defined_function.some_partitioned_table;
END;
$$ LANGUAGE plpgsql;
-- When I call the function twice
select partition_with_user_defined_function.query_a_partition_table();
query_a_partition_table
-------------------------
(1 row)
-- Then I get the same result both times (no rows)
-- Note: We're using a cached plan that includes a Dynamic Table Scan.
-- Ensure the dynamic table scan information in the cached plan does not get freed.
select partition_with_user_defined_function.query_a_partition_table();
query_a_partition_table
-------------------------
(1 row)
CREATE SCHEMA partition_with_user_defined_function;
-- Given there is a partitioned table
create table partition_with_user_defined_function.some_partitioned_table
(
a integer
)
partition by range (a) (
partition b start (0)
);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Greenplum Database data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
NOTICE: CREATE TABLE will create partition "some_partitioned_table_1_prt_b" for table "some_partitioned_table"
-- And a function that queried the partitioned table
CREATE OR REPLACE FUNCTION partition_with_user_defined_function.query_a_partition_table() RETURNS VOID AS
$$
BEGIN
PERFORM * FROM partition_with_user_defined_function.some_partitioned_table;
END;
$$ LANGUAGE plpgsql;
-- When I call the function twice
select partition_with_user_defined_function.query_a_partition_table();
query_a_partition_table
-------------------------
(1 row)
-- Then I get the same result both times (no rows)
-- Note: We're using a cached plan that includes a Dynamic Table Scan.
-- Ensure the dynamic table scan information in the cached plan does not get freed.
select partition_with_user_defined_function.query_a_partition_table();
query_a_partition_table
-------------------------
(1 row)
......@@ -64,7 +64,7 @@ test: rangefuncs_cdb gp_dqa subselect_gp subselect_gp2 olap_group olap_window_se
# 'partition' runs for a long time, so try to keep it together with other
# long-running tests.
test: partition partition1 partition_indexing parruleord
test: partition partition1 partition_indexing parruleord partition_with_user_defined_function
# 'partition_locking' gets confused if other backends run concurrently and
# hold locks.
test: partition_locking
......
CREATE SCHEMA partition_with_user_defined_function;
-- Given there is a partitioned table
create table partition_with_user_defined_function.some_partitioned_table
(
a integer
)
partition by range (a) (
partition b start (0)
);
-- And a function that queried the partitioned table
CREATE OR REPLACE FUNCTION partition_with_user_defined_function.query_a_partition_table() RETURNS VOID AS
$$
BEGIN
PERFORM * FROM partition_with_user_defined_function.some_partitioned_table;
END;
$$ LANGUAGE plpgsql;
-- When I call the function twice
select partition_with_user_defined_function.query_a_partition_table();
-- Then I get the same result both times (no rows)
-- Note: We're using a cached plan that includes a Dynamic Table Scan.
-- Ensure the dynamic table scan information in the cached plan does not get freed.
select partition_with_user_defined_function.query_a_partition_table();
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册