Skip to content

Commit 63f01bd

Browse files
committed
Mark array_sort with dynamic bool unshippable
In Postgres one can use a column value for the boolean value to `array_sort()` that indicates whether the sort should be reversed. In ClickHouse reverse sort requires a different function, so we can't use a dynamic value. When 1f2dedd added `array_sort()`, it simply pretended that a dynamic argument wasn't present and would always sort without reverse, which could be surprising. So move the determination of whether the boolean value is passed as a dynamic expression from `deparseFuncExpr()`, which is called and execution time, to `chfdw_is_shippable()`, which is called at planning time. This requires a node to be passed to `chfdw_is_shippable()` so it can evaluate the arguments, so add it as a parameter. Move the setting of the function name to the `CF_ARRAY_SORT_DESC` case of the switch statement in `deparseFuncExpr()` to ensure we don't overwrite the name in the cache of function definitions kept by `chfdw_check_for_custom_function()`. Add a test to validate that a dynamic argument causes the expression not to be passed down, and put it before the use of a constant to ensure that the function name isn't overwritten.
1 parent 1f2dedd commit 63f01bd

5 files changed

Lines changed: 43 additions & 23 deletions

File tree

src/deparse.c

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ foreign_expr_walker(Node * node,
421421
* can't be sent to remote because it might have incompatible
422422
* semantics on remote side.
423423
*/
424-
if (!chfdw_is_shippable(fe->funcid, ProcedureRelationId, fpinfo, &cdef))
424+
if (!chfdw_is_shippable(node, fe->funcid, ProcedureRelationId, fpinfo, &cdef))
425425
return false;
426426

427427
/*
@@ -472,7 +472,7 @@ foreign_expr_walker(Node * node,
472472
* (If the operator is shippable, we assume its underlying
473473
* function is too.)
474474
*/
475-
if (!chfdw_is_shippable(oe->opno, OperatorRelationId, fpinfo, NULL))
475+
if (!chfdw_is_shippable(node, oe->opno, OperatorRelationId, fpinfo, NULL))
476476
return false;
477477

478478
/*
@@ -589,7 +589,7 @@ foreign_expr_walker(Node * node,
589589
return false;
590590

591591
/* As usual, it must be shippable. */
592-
if (!chfdw_is_shippable(agg->aggfnoid, ProcedureRelationId, fpinfo, NULL))
592+
if (!chfdw_is_shippable(node, agg->aggfnoid, ProcedureRelationId, fpinfo, NULL))
593593
return false;
594594

595595
/* Features that ClickHouse doesn't support */
@@ -661,7 +661,7 @@ foreign_expr_walker(Node * node,
661661
return false;
662662

663663
/* The window function must be shippable */
664-
if (!chfdw_is_shippable(wfunc->winfnoid, ProcedureRelationId, fpinfo, NULL))
664+
if (!chfdw_is_shippable(node, wfunc->winfnoid, ProcedureRelationId, fpinfo, NULL))
665665
return false;
666666

667667
/* FILTER is not supported in ClickHouse window functions */
@@ -742,7 +742,7 @@ foreign_expr_walker(Node * node,
742742
* If result type of given expression is not shippable, it can't be sent
743743
* to remote because it might have incompatible semantics on remote side.
744744
*/
745-
if (check_type && !chfdw_is_shippable(exprType(node), TypeRelationId, fpinfo, NULL))
745+
if (check_type && !chfdw_is_shippable(node, exprType(node), TypeRelationId, fpinfo, NULL))
746746
{
747747
return false;
748748
}
@@ -2552,16 +2552,6 @@ deparseFuncExpr(FuncExpr * node, deparse_expr_cxt * context)
25522552
* depends on boolean arg, resolve before printing.
25532553
*/
25542554
cdef = chfdw_check_for_custom_function(node->funcid);
2555-
if (cdef && cdef->cf_type == CF_ARRAY_SORT_DESC)
2556-
{
2557-
Expr *desc_arg = (Expr *) list_nth(node->args, 1);
2558-
2559-
if (IsA(desc_arg, Const) && !((Const *) desc_arg)->constisnull
2560-
&& DatumGetBool(((Const *) desc_arg)->constvalue))
2561-
strcpy(cdef->custom_name, "arrayReverseSort");
2562-
else
2563-
strcpy(cdef->custom_name, "arraySort");
2564-
}
25652555
cdef = appendFunctionName(node->funcid, context);
25662556

25672557
if (cdef)
@@ -2746,11 +2736,17 @@ deparseFuncExpr(FuncExpr * node, deparse_expr_cxt * context)
27462736
appendStringInfoChar(buf, ')');
27472737
return;
27482738
case CF_ARRAY_SORT_DESC:
2749-
/* name resolved before appendFunctionName, drop boolean arg */
2750-
appendStringInfoChar(buf, '(');
2751-
deparseExpr((Expr *) linitial(node->args), context);
2752-
appendStringInfoChar(buf, ')');
2753-
return;
2739+
{
2740+
/* Determine function name reverse boolean arg. */
2741+
Const *desc_arg = (Const *) list_nth(node->args, 1);
2742+
2743+
appendStringInfoString(buf, !desc_arg->constisnull && DatumGetBool(desc_arg->constvalue) ? "arrayReverseSort" : "arraySort");
2744+
appendStringInfoChar(buf, '(');
2745+
deparseExpr((Expr *) linitial(node->args), context);
2746+
appendStringInfoChar(buf, ')');
2747+
return;
2748+
}
2749+
27542750
case CF_ARRAY_FILL:
27552751
/* arrayWithConstant(n, val): swap args */
27562752
appendStringInfoChar(buf, '(');

src/include/fdw.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ extern Datum ch_timestamp_out(PG_FUNCTION_ARGS);
371371
extern Datum ch_date_out(PG_FUNCTION_ARGS);
372372
extern Datum ch_time_out(PG_FUNCTION_ARGS);
373373

374-
extern bool chfdw_is_shippable(Oid objectId, Oid classId, CHFdwRelationInfo * fpinfo,
374+
extern bool chfdw_is_shippable(Node * node, Oid objectId, Oid classId, CHFdwRelationInfo * fpinfo,
375375
CustomObjectDef * *outcdef);
376376
extern double time_diff(struct timeval *prior, struct timeval *latter);
377377

src/shipable.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ chfdw_is_builtin(Oid objectId)
161161
* Is this object (function/operator/type) shippable to foreign server?
162162
*/
163163
bool
164-
chfdw_is_shippable(Oid objectId, Oid classId, CHFdwRelationInfo * fpinfo,
164+
chfdw_is_shippable(Node * node, Oid objectId, Oid classId, CHFdwRelationInfo * fpinfo,
165165
CustomObjectDef * *outcdef)
166166
{
167167
ShippableCacheKey key;
@@ -192,6 +192,19 @@ chfdw_is_shippable(Oid objectId, Oid classId, CHFdwRelationInfo * fpinfo,
192192
{
193193
if (outcdef != NULL)
194194
*outcdef = cdef;
195+
196+
if (cdef->cf_type == CF_ARRAY_SORT_DESC)
197+
{
198+
/*
199+
* If the boolean argument passed to array_sort(arr, bool) is
200+
* dynamic, we can't push it down.
201+
*/
202+
Expr *desc_arg = (Expr *) list_nth(((FuncExpr *) node)->args, 1);
203+
204+
if (!IsA(desc_arg, Const))
205+
/* No support for a dynamic value here. */
206+
return false;
207+
}
195208
return (cdef->cf_type != CF_UNSHIPPABLE);
196209
}
197210
}

test/expected/array_functions.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ NOTICE: array_reverse PUSHED DOWN: t
201201
NOTICE: (1,"{10,20,30}","{a,b,c}",aa-bb-cc)
202202
NOTICE: array_sort PUSHED DOWN: f
203203
NOTICE: (3,{60},{f},"Edit -> Insert -> Line Break")
204+
NOTICE: array_sort(x, dynamic) NOT PUSHED DOWN: t
205+
NOTICE: (1,"{10,20,30}","{a,b,c}",aa-bb-cc)
204206
NOTICE: array_sort(x, true) PUSHED DOWN: t
205207
NOTICE: (1,"{10,20,30}","{a,b,c}",aa-bb-cc)
206208
NOTICE: array_sort(x, true, true) NOT PUSHED DOWN: t

test/sql/array_functions.sql

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,14 @@ DECLARE
130130
"where": "array_sort(vals, true) = vals",
131131
"push": "((arraySort(vals) = vals))"
132132
}$_$,
133-
-- PG18+ 'array_sort(vals, true) = ARRAY[30,20,10]'
133+
-- PG18+ unshippable: 'array_sort(vals, dynamic) = ARRAY[30,20,10]'
134+
-- Keep before array_sort(vals, const) to ensure function names not
135+
-- replaced.
136+
$_${
137+
"func": "array_sort(x, dynamic)",
138+
"where": "array_sort(vals, (select true)) = ARRAY[30,20,10]"
139+
}$_$,
140+
-- PG18+ 'array_sort(vals, const) = ARRAY[30,20,10]'
134141
$_${
135142
"func": "array_sort(x, true)",
136143
"where": "array_sort(vals, true) = ARRAY[30,20,10]",
@@ -166,6 +173,8 @@ BEGIN
166173
RAISE NOTICE '(1,"{10,20,30}","{a,b,c}",aa-bb-cc)';
167174
RAISE NOTICE 'array_sort PUSHED DOWN: f';
168175
RAISE NOTICE '(3,{60},{f},"Edit -> Insert -> Line Break")';
176+
RAISE NOTICE 'array_sort(x, dynamic) NOT PUSHED DOWN: t';
177+
RAISE NOTICE '(1,"{10,20,30}","{a,b,c}",aa-bb-cc)';
169178
RAISE NOTICE 'array_sort(x, true) PUSHED DOWN: t';
170179
RAISE NOTICE '(1,"{10,20,30}","{a,b,c}",aa-bb-cc)';
171180
RAISE NOTICE 'array_sort(x, true, true) NOT PUSHED DOWN: t';

0 commit comments

Comments
 (0)