Merge pull request #3498 from citusdata/fix_null_crash

Do not prune shards if the distribution key is NULL
pull/3499/head^2
Önder Kalacı 2020-02-13 17:21:31 +01:00 committed by GitHub
commit 6225f37b91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 2031 additions and 20 deletions

View File

@ -545,8 +545,8 @@ HandleDeferredShardPruningForFastPathQueries(DistributedPlan *distributedPlan)
bool isMultiShardQuery = false;
List *shardIntervalList =
TargetShardIntervalForFastPathQuery(workerJob->jobQuery,
&workerJob->partitionKeyValue,
&isMultiShardQuery, NULL);
&isMultiShardQuery, NULL,
&workerJob->partitionKeyValue);
/*
* A fast-path router query can only yield multiple shards when the parameter

View File

@ -2091,8 +2091,9 @@ PlanRouterQuery(Query *originalQuery,
plannerRestrictionContext->fastPathRestrictionContext->distributionKeyValue;
List *shardIntervalList =
TargetShardIntervalForFastPathQuery(originalQuery, partitionValueConst,
&isMultiShardQuery, distributionKeyValue);
TargetShardIntervalForFastPathQuery(originalQuery, &isMultiShardQuery,
distributionKeyValue,
partitionValueConst);
/*
* This could only happen when there is a parameter on the distribution key.
@ -2375,25 +2376,32 @@ GetAnchorShardId(List *prunedShardIntervalListList)
* one list of a a one shard interval (see FastPathRouterQuery()
* for the detail).
*
* Also set the outgoing partition column value if requested via
* partitionValueConst
* If the caller requested the distributionKey value that this function
* yields, set outputPartitionValueConst.
*/
List *
TargetShardIntervalForFastPathQuery(Query *query, Const **partitionValueConst,
bool *isMultiShardQuery, Const *distributionKeyValue)
TargetShardIntervalForFastPathQuery(Query *query, bool *isMultiShardQuery,
Const *inputDistributionKeyValue,
Const **outputPartitionValueConst)
{
Oid relationId = ExtractFirstDistributedTableId(query);
if (distributionKeyValue)
if (PartitionMethod(relationId) == DISTRIBUTE_BY_NONE)
{
/* we don't need to do shard pruning for reference tables */
return list_make1(LoadShardIntervalList(relationId));
}
if (inputDistributionKeyValue && !inputDistributionKeyValue->constisnull)
{
DistTableCacheEntry *cache = DistributedTableCacheEntry(relationId);
ShardInterval *shardInterval =
FindShardInterval(distributionKeyValue->constvalue, cache);
FindShardInterval(inputDistributionKeyValue->constvalue, cache);
if (partitionValueConst != NULL)
if (outputPartitionValueConst != NULL)
{
/* set the outgoing partition column value if requested */
*partitionValueConst = distributionKeyValue;
*outputPartitionValueConst = inputDistributionKeyValue;
}
List *shardIntervalList = list_make1(shardInterval);
@ -2402,10 +2410,24 @@ TargetShardIntervalForFastPathQuery(Query *query, Const **partitionValueConst,
Node *quals = query->jointree->quals;
int relationIndex = 1;
Const *queryPartitionValueConst = NULL;
/*
* We couldn't do the shard pruning based on inputDistributionKeyValue as it might
* be passed as NULL. Still, we can search the quals for distribution key.
*/
Const *distributionKeyValueInQuals = NULL;
List *prunedShardIntervalList =
PruneShards(relationId, relationIndex, make_ands_implicit((Expr *) quals),
&queryPartitionValueConst);
&distributionKeyValueInQuals);
if (!distributionKeyValueInQuals || distributionKeyValueInQuals->constisnull)
{
/*
* If the distribution key equals to NULL, we prefer to treat it as a zero shard
* query as it cannot return any rows.
*/
return NIL;
}
/* we're only expecting single shard from a single table */
Node *distKey PG_USED_FOR_ASSERTS_ONLY = NULL;
@ -2416,10 +2438,10 @@ TargetShardIntervalForFastPathQuery(Query *query, Const **partitionValueConst,
*isMultiShardQuery = true;
}
else if (list_length(prunedShardIntervalList) == 1 &&
partitionValueConst != NULL)
outputPartitionValueConst != NULL)
{
/* set the outgoing partition column value if requested */
*partitionValueConst = queryPartitionValueConst;
*outputPartitionValueConst = distributionKeyValueInQuals;
}
return list_make1(prunedShardIntervalList);

View File

@ -749,13 +749,21 @@ AddPartitionKeyRestrictionToInstance(ClauseWalkerContext *context, OpExpr *opCla
constantClause);
if (constantClause == NULL)
{
/* couldn't coerce value, so we note this as a restriction we don't grok */
/* couldn't coerce value, so we save it in otherRestrictions */
prune->otherRestrictions = lappend(prune->otherRestrictions, opClause);
return;
}
}
if (constantClause->constisnull)
{
/* we cannot do pruning for NULL values, so we save it in otherRestrictions */
prune->otherRestrictions = lappend(prune->otherRestrictions, opClause);
return;
}
/* at this point, we'd better be able to pass binary Datums to comparison functions */
Assert(IsBinaryCoercible(constantClause->consttype, partitionColumn->vartype));

View File

@ -77,9 +77,9 @@ extern List * WorkersContainingAllShards(List *prunedShardIntervalsList);
extern uint64 GetAnchorShardId(List *relationShardList);
extern List * TargetShardIntervalForFastPathQuery(Query *query,
Const **partitionValueConst,
bool *isMultiShardQuery,
Const *distributionKeyValue);
Const *inputDistributionKeyValue,
Const **outGoingPartitionValueConst);
extern void GenerateSingleShardRouterTaskList(Job *job,
List *relationShardList,
List *placementList, uint64 shardId);

View File

@ -1636,6 +1636,68 @@ DEBUG: Plan is router executable
41 | 1 | aznavour | 11814
(5 rows)
EXECUTE author_articles(NULL);
id | author_id | title | word_count
---------------------------------------------------------------------
(0 rows)
EXECUTE author_articles(NULL);
id | author_id | title | word_count
---------------------------------------------------------------------
(0 rows)
EXECUTE author_articles(NULL);
id | author_id | title | word_count
---------------------------------------------------------------------
(0 rows)
EXECUTE author_articles(NULL);
id | author_id | title | word_count
---------------------------------------------------------------------
(0 rows)
EXECUTE author_articles(NULL);
id | author_id | title | word_count
---------------------------------------------------------------------
(0 rows)
EXECUTE author_articles(NULL);
id | author_id | title | word_count
---------------------------------------------------------------------
(0 rows)
EXECUTE author_articles(NULL);
id | author_id | title | word_count
---------------------------------------------------------------------
(0 rows)
PREPARE author_articles_update(int) AS
UPDATE articles_hash SET title = 'test' WHERE author_id = $1;
EXECUTE author_articles_update(NULL);
DEBUG: Deferred pruning for a fast-path router query
DEBUG: Creating router plan
DEBUG: Plan is router executable
EXECUTE author_articles_update(NULL);
DEBUG: Deferred pruning for a fast-path router query
DEBUG: Creating router plan
DEBUG: Plan is router executable
EXECUTE author_articles_update(NULL);
DEBUG: Deferred pruning for a fast-path router query
DEBUG: Creating router plan
DEBUG: Plan is router executable
EXECUTE author_articles_update(NULL);
DEBUG: Deferred pruning for a fast-path router query
DEBUG: Creating router plan
DEBUG: Plan is router executable
EXECUTE author_articles_update(NULL);
DEBUG: Deferred pruning for a fast-path router query
DEBUG: Creating router plan
DEBUG: Plan is router executable
EXECUTE author_articles_update(NULL);
DEBUG: Deferred pruning for a fast-path router query
DEBUG: Creating router plan
DEBUG: Plan is router executable
EXECUTE author_articles_update(NULL);
-- queries inside plpgsql functions could be router plannable
CREATE OR REPLACE FUNCTION author_articles_max_id() RETURNS int AS $$
DECLARE

File diff suppressed because it is too large Load Diff

View File

@ -201,7 +201,7 @@ test: multi_transaction_recovery
# multi_router_planner creates hash partitioned tables.
# ---------
test: multi_copy fast_path_router_modify
test: multi_router_planner multi_router_planner_fast_path
test: multi_router_planner multi_router_planner_fast_path null_parameters
# ----------
# multi_large_shardid loads more lineitem data using high shard identifiers

View File

@ -666,6 +666,25 @@ EXECUTE author_articles(1);
EXECUTE author_articles(1);
EXECUTE author_articles(1);
EXECUTE author_articles(NULL);
EXECUTE author_articles(NULL);
EXECUTE author_articles(NULL);
EXECUTE author_articles(NULL);
EXECUTE author_articles(NULL);
EXECUTE author_articles(NULL);
EXECUTE author_articles(NULL);
PREPARE author_articles_update(int) AS
UPDATE articles_hash SET title = 'test' WHERE author_id = $1;
EXECUTE author_articles_update(NULL);
EXECUTE author_articles_update(NULL);
EXECUTE author_articles_update(NULL);
EXECUTE author_articles_update(NULL);
EXECUTE author_articles_update(NULL);
EXECUTE author_articles_update(NULL);
EXECUTE author_articles_update(NULL);
-- queries inside plpgsql functions could be router plannable
CREATE OR REPLACE FUNCTION author_articles_max_id() RETURNS int AS $$
DECLARE

View File

@ -0,0 +1,315 @@
-- this file contain tests with pruning of NULL
-- values with prepared statements
CREATE SCHEMA null_parameters;
SET search_path TO null_parameters;
SET citus.next_shard_id TO 1680000;
CREATE TABLE text_dist_column (key text, value text);
SELECT create_distributed_table('text_dist_column', 'key');
SET client_min_messages TO DEBUG;
PREPARE null_select_on_text AS SELECT count(*) FROM text_dist_column WHERE key = NULL;
EXECUTE null_select_on_text;
EXECUTE null_select_on_text;
EXECUTE null_select_on_text;
EXECUTE null_select_on_text;
EXECUTE null_select_on_text;
EXECUTE null_select_on_text;
PREPARE null_select_on_text_param(text) AS SELECT count(*) FROM text_dist_column WHERE key = $1;
EXECUTE null_select_on_text_param(NULL);
EXECUTE null_select_on_text_param(NULL);
EXECUTE null_select_on_text_param(5::text);
EXECUTE null_select_on_text_param(NULL);
EXECUTE null_select_on_text_param(NULL);
EXECUTE null_select_on_text_param(NULL);
EXECUTE null_select_on_text_param(NULL);
EXECUTE null_select_on_text_param(NULL);
EXECUTE null_select_on_text_param(NULL::varchar);
EXECUTE null_select_on_text_param('test'::varchar);
EXECUTE null_select_on_text_param(5::text);
PREPARE null_select_on_text_param_and_false(text) AS SELECT count(*) FROM text_dist_column WHERE key = $1 AND false;
EXECUTE null_select_on_text_param_and_false(NULL);
EXECUTE null_select_on_text_param_and_false(NULL);
EXECUTE null_select_on_text_param_and_false(NULL);
EXECUTE null_select_on_text_param_and_false(NULL);
EXECUTE null_select_on_text_param_and_false(NULL);
EXECUTE null_select_on_text_param_and_false(NULL);
EXECUTE null_select_on_text_param_and_false(NULL);
PREPARE null_select_on_text_param_and_in(text) AS SELECT count(*) FROM text_dist_column WHERE key IN ($1);
EXECUTE null_select_on_text_param_and_in(NULL);
EXECUTE null_select_on_text_param_and_in(NULL);
EXECUTE null_select_on_text_param_and_in(NULL);
EXECUTE null_select_on_text_param_and_in(NULL);
EXECUTE null_select_on_text_param_and_in(NULL);
EXECUTE null_select_on_text_param_and_in(NULL);
PREPARE null_select_on_text_param_and_in_2(text) AS SELECT count(*) FROM text_dist_column WHERE key IN ($1, 'test');
EXECUTE null_select_on_text_param_and_in_2(NULL);
EXECUTE null_select_on_text_param_and_in_2(NULL);
EXECUTE null_select_on_text_param_and_in_2(NULL);
EXECUTE null_select_on_text_param_and_in_2(NULL);
EXECUTE null_select_on_text_param_and_in_2(NULL);
EXECUTE null_select_on_text_param_and_in_2(NULL);
PREPARE null_select_on_text_param_and_in_3(text, text) AS SELECT count(*) FROM text_dist_column WHERE key IN ($1, $2);
EXECUTE null_select_on_text_param_and_in_3(NULL, NULL);
EXECUTE null_select_on_text_param_and_in_3(NULL, NULL);
EXECUTE null_select_on_text_param_and_in_3(NULL, NULL);
EXECUTE null_select_on_text_param_and_in_3(NULL, NULL);
EXECUTE null_select_on_text_param_and_in_3(NULL, NULL);
EXECUTE null_select_on_text_param_and_in_3(NULL, NULL);
PREPARE null_select_on_text_param_and_in_4(text) AS SELECT count(*) FROM text_dist_column WHERE key IN ($1) AND false;
EXECUTE null_select_on_text_param_and_in_4(NULL);
EXECUTE null_select_on_text_param_and_in_4(NULL);
EXECUTE null_select_on_text_param_and_in_4(NULL);
EXECUTE null_select_on_text_param_and_in_4(NULL);
EXECUTE null_select_on_text_param_and_in_4(NULL);
EXECUTE null_select_on_text_param_and_in_4(NULL);
-- not a fast-path, still good to run
PREPARE null_select_on_text_param_and_in_5(text, text) AS SELECT count(*) FROM text_dist_column WHERE key = $1 OR key = $2;
EXECUTE null_select_on_text_param_and_in_5(NULL, NULL);
EXECUTE null_select_on_text_param_and_in_5(NULL, NULL);
EXECUTE null_select_on_text_param_and_in_5(1, NULL);
EXECUTE null_select_on_text_param_and_in_5(NULL, NULL);
EXECUTE null_select_on_text_param_and_in_5(NULL, NULL);
EXECUTE null_select_on_text_param_and_in_5(NULL, NULL);
EXECUTE null_select_on_text_param_and_in_5(NULL, NULL);
EXECUTE null_select_on_text_param_and_in_5(NULL, NULL);
EXECUTE null_select_on_text_param_and_in_5(1, NULL);
-- not a fast-path, still good to have
PREPARE null_select_on_text_param_and_in_6(text) AS SELECT count(*) FROM text_dist_column WHERE key NOT IN (SELECT value FROM text_dist_column WHERE key = $1);
EXECUTE null_select_on_text_param_and_in_6(NULL);
EXECUTE null_select_on_text_param_and_in_6(NULL);
EXECUTE null_select_on_text_param_and_in_6(NULL);
EXECUTE null_select_on_text_param_and_in_6(NULL);
EXECUTE null_select_on_text_param_and_in_6(NULL);
EXECUTE null_select_on_text_param_and_in_6(NULL);
EXECUTE null_select_on_text_param_and_in_6(NULL);
-- different expression types which may not be fast-path queries
PREPARE null_select_on_text_param_7(text) AS SELECT count(*) FROM text_dist_column WHERE (key = $1) is true;
EXECUTE null_select_on_text_param_7(NULL);
EXECUTE null_select_on_text_param_7(NULL);
EXECUTE null_select_on_text_param_7(NULL);
EXECUTE null_select_on_text_param_7(NULL);
EXECUTE null_select_on_text_param_7(NULL);
EXECUTE null_select_on_text_param_7(NULL);
EXECUTE null_select_on_text_param_7(NULL);
-- different expression types which may not be fast-path queries
PREPARE null_select_on_text_param_8(text) AS SELECT count(*) FROM text_dist_column WHERE key = ANY(ARRAY[$1]);
EXECUTE null_select_on_text_param_8(NULL);
EXECUTE null_select_on_text_param_8(NULL);
EXECUTE null_select_on_text_param_8(NULL);
EXECUTE null_select_on_text_param_8(NULL);
EXECUTE null_select_on_text_param_8(NULL);
EXECUTE null_select_on_text_param_8(NULL);
EXECUTE null_select_on_text_param_8(NULL);
PREPARE null_select_on_text_param_9(text) AS SELECT count(*) FROM text_dist_column WHERE key = ANY(ARRAY[$1, 'test']);
EXECUTE null_select_on_text_param_9(NULL);
EXECUTE null_select_on_text_param_9(NULL);
EXECUTE null_select_on_text_param_9(NULL);
EXECUTE null_select_on_text_param_9(NULL);
EXECUTE null_select_on_text_param_9(NULL);
EXECUTE null_select_on_text_param_9(NULL);
EXECUTE null_select_on_text_param_9(NULL);
-- different expression types which may not be fast-path queries
PREPARE null_select_on_text_param_10(text) AS SELECT count(*) FROM text_dist_column WHERE key = ALL(ARRAY[$1]);
EXECUTE null_select_on_text_param_10(NULL);
EXECUTE null_select_on_text_param_10(NULL);
EXECUTE null_select_on_text_param_10(NULL);
EXECUTE null_select_on_text_param_10(NULL);
EXECUTE null_select_on_text_param_10(NULL);
EXECUTE null_select_on_text_param_10(NULL);
EXECUTE null_select_on_text_param_10(NULL);
-- different expression types which may not be fast-path queries
PREPARE null_select_on_text_param_11(text) AS SELECT count(*) FROM text_dist_column WHERE (CASE WHEN key > $1 THEN key::int / 100 > 1 ELSE false END);
EXECUTE null_select_on_text_param_11(NULL);
EXECUTE null_select_on_text_param_11(NULL);
EXECUTE null_select_on_text_param_11(NULL);
EXECUTE null_select_on_text_param_11(NULL);
EXECUTE null_select_on_text_param_11(NULL);
EXECUTE null_select_on_text_param_11(NULL);
EXECUTE null_select_on_text_param_11(NULL);
EXECUTE null_select_on_text_param_11(NULL);
-- different expression types which may not be fast-path queries
PREPARE null_select_on_text_param_12(text) AS SELECT count(*) FROM text_dist_column WHERE COALESCE(($1::int/50000)::bool, false);
EXECUTE null_select_on_text_param_12(NULL);
EXECUTE null_select_on_text_param_12(NULL);
EXECUTE null_select_on_text_param_12(NULL);
EXECUTE null_select_on_text_param_12(NULL);
EXECUTE null_select_on_text_param_12(NULL);
EXECUTE null_select_on_text_param_12(NULL);
EXECUTE null_select_on_text_param_12(NULL);
-- different expression types which may not be fast-path queries
PREPARE null_select_on_text_param_13(text) AS SELECT count(*) FROM text_dist_column WHERE NULLIF(($1::int/50000)::bool, false);
EXECUTE null_select_on_text_param_13(NULL);
EXECUTE null_select_on_text_param_13(NULL);
EXECUTE null_select_on_text_param_13(NULL);
EXECUTE null_select_on_text_param_13(NULL);
EXECUTE null_select_on_text_param_13(NULL);
EXECUTE null_select_on_text_param_13(NULL);
EXECUTE null_select_on_text_param_13(NULL);
PREPARE null_select_on_text_param_14(text) AS SELECT count(*) FROM text_dist_column WHERE key = $1 AND 0!=0;
EXECUTE null_select_on_text_param_14(NULL);
EXECUTE null_select_on_text_param_14(NULL);
EXECUTE null_select_on_text_param_14(NULL);
EXECUTE null_select_on_text_param_14(NULL);
EXECUTE null_select_on_text_param_14(NULL);
EXECUTE null_select_on_text_param_14(NULL);
EXECUTE null_select_on_text_param_14(NULL);
EXECUTE null_select_on_text_param_14(NULL);
PREPARE null_select_on_text_param_15(text) AS SELECT count(*) FROM text_dist_column WHERE row(key, 100) > row($1, 0);
EXECUTE null_select_on_text_param_15(NULL);
EXECUTE null_select_on_text_param_15(NULL);
EXECUTE null_select_on_text_param_15(NULL);
EXECUTE null_select_on_text_param_15(NULL);
EXECUTE null_select_on_text_param_15(NULL);
EXECUTE null_select_on_text_param_15(NULL);
EXECUTE null_select_on_text_param_15(NULL);
EXECUTE null_select_on_text_param_15(NULL);
PREPARE null_select_on_text_param_16(text) AS SELECT count(*) FROM text_dist_column WHERE key IS DISTINCT FROM $1;
EXECUTE null_select_on_text_param_16(NULL);
EXECUTE null_select_on_text_param_16(NULL);
EXECUTE null_select_on_text_param_16(NULL);
EXECUTE null_select_on_text_param_16(NULL);
EXECUTE null_select_on_text_param_16(NULL);
EXECUTE null_select_on_text_param_16(NULL);
EXECUTE null_select_on_text_param_16(NULL);
EXECUTE null_select_on_text_param_16(NULL);
PREPARE null_select_on_text_param_17(text) AS SELECT count(*) FROM text_dist_column WHERE key = $1 AND 0!=1;
EXECUTE null_select_on_text_param_17(NULL);
EXECUTE null_select_on_text_param_17(NULL);
EXECUTE null_select_on_text_param_17(NULL);
EXECUTE null_select_on_text_param_17(NULL);
EXECUTE null_select_on_text_param_17(NULL);
EXECUTE null_select_on_text_param_17(NULL);
EXECUTE null_select_on_text_param_17(NULL);
EXECUTE null_select_on_text_param_17(NULL);
PREPARE null_select_on_text_param_18(text) AS SELECT count(*) FROM text_dist_column WHERE key = upper($1);
EXECUTE null_select_on_text_param_18(NULL);
EXECUTE null_select_on_text_param_18(NULL);
EXECUTE null_select_on_text_param_18(NULL);
EXECUTE null_select_on_text_param_18(NULL);
EXECUTE null_select_on_text_param_18(NULL);
EXECUTE null_select_on_text_param_18(NULL);
EXECUTE null_select_on_text_param_18(NULL);
PREPARE null_select_on_text_param_19(text) AS SELECT count(*) FROM text_dist_column WHERE key = $1::varchar(4);
EXECUTE null_select_on_text_param_19(NULL);
EXECUTE null_select_on_text_param_19(NULL);
EXECUTE null_select_on_text_param_19(NULL);
EXECUTE null_select_on_text_param_19(NULL);
EXECUTE null_select_on_text_param_19(NULL);
EXECUTE null_select_on_text_param_19(NULL);
EXECUTE null_select_on_text_param_19(NULL);
PREPARE null_update_on_text AS UPDATE text_dist_column SET value = '' WHERE key = NULL;
EXECUTE null_update_on_text(NULL);
EXECUTE null_update_on_text(NULL);
EXECUTE null_update_on_text(NULL);
EXECUTE null_update_on_text(NULL);
EXECUTE null_update_on_text(NULL);
EXECUTE null_update_on_text(NULL);
PREPARE null_update_on_text_param(text) AS UPDATE text_dist_column SET value = '' WHERE key = $1;
EXECUTE null_update_on_text_param(NULL);
EXECUTE null_update_on_text_param(NULL);
EXECUTE null_update_on_text_param(NULL);
EXECUTE null_update_on_text_param(NULL);
EXECUTE null_update_on_text_param(NULL);
EXECUTE null_update_on_text_param(NULL);
EXECUTE null_update_on_text_param(NULL);
PREPARE null_update_on_text_param_and_false(text) AS UPDATE text_dist_column SET value = '' WHERE key = $1 AND false;
EXECUTE null_update_on_text_param_and_false(NULL);
EXECUTE null_update_on_text_param_and_false(NULL);
EXECUTE null_update_on_text_param_and_false(NULL);
EXECUTE null_update_on_text_param_and_false(NULL);
EXECUTE null_update_on_text_param_and_false(NULL);
EXECUTE null_update_on_text_param_and_false(NULL);
EXECUTE null_update_on_text_param_and_false(NULL);
PREPARE null_update_on_text_param_and_in(text) AS UPDATE text_dist_column SET value = '' WHERE key IN ($1);
EXECUTE null_update_on_text_param_and_in(NULL);
EXECUTE null_update_on_text_param_and_in(NULL);
EXECUTE null_update_on_text_param_and_in(NULL);
EXECUTE null_update_on_text_param_and_in(NULL);
EXECUTE null_update_on_text_param_and_in(NULL);
EXECUTE null_update_on_text_param_and_in(NULL);
EXECUTE null_update_on_text_param_and_in(NULL);
PREPARE null_update_on_text_param_and_in_2(text) AS UPDATE text_dist_column SET value = '' WHERE key IN ($1, 'test');
EXECUTE null_update_on_text_param_and_in_2(NULL);
EXECUTE null_update_on_text_param_and_in_2(NULL);
EXECUTE null_update_on_text_param_and_in_2(NULL);
EXECUTE null_update_on_text_param_and_in_2(NULL);
EXECUTE null_update_on_text_param_and_in_2(NULL);
EXECUTE null_update_on_text_param_and_in_2(NULL);
EXECUTE null_update_on_text_param_and_in_2(NULL);
PREPARE null_update_on_text_param_and_in_3(text, text) AS UPDATE text_dist_column SET value = '' WHERE key IN ($1, $2);
EXECUTE null_update_on_text_param_and_in_3(NULL, NULL);
EXECUTE null_update_on_text_param_and_in_3(NULL, NULL);
EXECUTE null_update_on_text_param_and_in_3(NULL, NULL);
EXECUTE null_update_on_text_param_and_in_3(NULL, NULL);
EXECUTE null_update_on_text_param_and_in_3(NULL, NULL);
EXECUTE null_update_on_text_param_and_in_3(NULL, NULL);
EXECUTE null_update_on_text_param_and_in_3(NULL, 'test');
PREPARE null_update_on_text_param_and_in_4(text) AS UPDATE text_dist_column SET value = '' WHERE key IN ($1) and false;
EXECUTE null_update_on_text_param_and_in_4(NULL);
EXECUTE null_update_on_text_param_and_in_4(NULL);
EXECUTE null_update_on_text_param_and_in_4(NULL);
EXECUTE null_update_on_text_param_and_in_4(NULL);
EXECUTE null_update_on_text_param_and_in_4(NULL);
EXECUTE null_update_on_text_param_and_in_4(NULL);
EXECUTE null_update_on_text_param_and_in_4(NULL);
-- sanity check with JSBONB column
CREATE TABLE jsonb_dist_column (key jsonb, value text);
SELECT create_distributed_table('jsonb_dist_column', 'key');
PREPARE null_select_on_json_param(jsonb) AS SELECT count(*) FROM jsonb_dist_column WHERE key = $1;
EXECUTE null_select_on_json_param(NULL);
EXECUTE null_select_on_json_param(NULL);
EXECUTE null_select_on_json_param(NULL);
EXECUTE null_select_on_json_param(NULL);
EXECUTE null_select_on_json_param(NULL);
EXECUTE null_select_on_json_param(NULL);
EXECUTE null_select_on_json_param(NULL);
SET client_min_messages TO ERROR;
DROP SCHEMA null_parameters CASCADE;