Fix a crash with inserting domain composite types in coord. evaluation (#4231)

Use short lived per-tuple context in citus_evaluate_expr like
(pg) evaluate_expr does.

We should not use planState->ExprContext when evaluating expressions
as it might lead to freeing the same executor twice (first one happens
in citus_evaluate_expr itself and the other one happens when postgres
doing clean-up for the top level executor state), which in turn might
cause seg.faults.

However, now as we don't have necessary planState info to evaluate
prepared statements, we also add planState->es_param_list_info to
per-tuple ExprContext.
pull/3597/head
Onur Tirtir 2020-10-13 14:19:59 +03:00 committed by GitHub
parent df185179c3
commit 8efca3b60a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 9 deletions

View File

@ -309,7 +309,6 @@ citus_evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
PlanState *planState = NULL;
EState *estate;
ExprState *exprstate;
ExprContext *econtext;
Datum const_val;
bool const_is_null;
int16 resultTypLen;
@ -357,15 +356,19 @@ citus_evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
*/
exprstate = ExecInitExpr(expr, planState);
if (planState != NULL)
/*
* Get short lived per tuple context as evaluate_expr does. Here we don't
* use planState->ExprContext as it might cause double-free'ing executor
* state.
*/
ExprContext *econtext = GetPerTupleExprContext(estate);
if (planState)
{
/* use executor's context to pass down parameters */
econtext = planState->ps_ExprContext;
}
else
{
/* when called from a function, use a default context */
econtext = GetPerTupleExprContext(estate);
/*
* If planState exists, then we add es_param_list_info to per tuple
* ExprContext as we need them when evaluating prepared statements.
*/
econtext->ecxt_param_list_info = planState->state->es_param_list_info;
}
/*

View File

@ -580,5 +580,38 @@ SELECT count(*) FROM coordinator_evaluation_table_2 WHERE key = 101;
7
(1 row)
CREATE TYPE comptype_int as (int_a int);
CREATE DOMAIN domain_comptype_int AS comptype_int CHECK ((VALUE).int_a > 0);
-- citus does not propagate domain types
SELECT run_command_on_workers(
$$
CREATE DOMAIN coordinator_evaluation.domain_comptype_int AS coordinator_evaluation.comptype_int CHECK ((VALUE).int_a > 0)
$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,"CREATE DOMAIN")
(localhost,57638,t,"CREATE DOMAIN")
(2 rows)
CREATE TABLE reference_table(column_a coordinator_evaluation.domain_comptype_int);
SELECT create_reference_table('reference_table');
create_reference_table
---------------------------------------------------------------------
(1 row)
INSERT INTO reference_table (column_a) VALUES ('(1)');
INSERT INTO reference_table (column_a) VALUES ('(2)'), ('(3)');
INSERT INTO reference_table VALUES ('(4)'), ('(5)');
SELECT * FROM reference_table ORDER BY 1;
column_a
---------------------------------------------------------------------
(1)
(2)
(3)
(4)
(5)
(5 rows)
SET client_min_messages TO ERROR;
DROP SCHEMA coordinator_evaluation CASCADE;

View File

@ -210,5 +210,22 @@ CALL test_procedure_2(100);
CALL test_procedure_2(100);
SELECT count(*) FROM coordinator_evaluation_table_2 WHERE key = 101;
CREATE TYPE comptype_int as (int_a int);
CREATE DOMAIN domain_comptype_int AS comptype_int CHECK ((VALUE).int_a > 0);
-- citus does not propagate domain types
SELECT run_command_on_workers(
$$
CREATE DOMAIN coordinator_evaluation.domain_comptype_int AS coordinator_evaluation.comptype_int CHECK ((VALUE).int_a > 0)
$$);
CREATE TABLE reference_table(column_a coordinator_evaluation.domain_comptype_int);
SELECT create_reference_table('reference_table');
INSERT INTO reference_table (column_a) VALUES ('(1)');
INSERT INTO reference_table (column_a) VALUES ('(2)'), ('(3)');
INSERT INTO reference_table VALUES ('(4)'), ('(5)');
SELECT * FROM reference_table ORDER BY 1;
SET client_min_messages TO ERROR;
DROP SCHEMA coordinator_evaluation CASCADE;