Skip to content

Commit cfbc778

Browse files
Pushdown hyperbolic functions (#78)
Signed-off-by: Ahmet Gedemenli <[email protected]>
1 parent c5684c6 commit cfbc778

File tree

6 files changed

+114
-1
lines changed

6 files changed

+114
-1
lines changed

duckdb_pglake/src/duckdb_pglake_extension.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,37 @@ inline void ThrowInternalError(DataChunk &args, ExpressionState &state, Vector &
7575
throw InternalException(str);
7676
}
7777

78+
79+
inline void AcoshPG(DataChunk &args, ExpressionState &state, Vector &result)
80+
{
81+
auto &input_vector = args.data[0];
82+
83+
UnaryExecutor::Execute<double, double>(
84+
input_vector, result, args.size(),
85+
[&](double value) {
86+
if (value < 1.0) {
87+
throw InvalidInputException("input is out of range");
88+
}
89+
return std::acosh(value);
90+
});
91+
}
92+
93+
94+
inline void AtanhPG(DataChunk &args, ExpressionState &state, Vector &result)
95+
{
96+
auto &input_vector = args.data[0];
97+
98+
UnaryExecutor::Execute<double, double>(
99+
input_vector, result, args.size(),
100+
[&](double value) {
101+
if (value < -1.0 || value > 1.0) {
102+
throw InvalidInputException("input is out of range");
103+
}
104+
return std::atanh(value);
105+
});
106+
}
107+
108+
78109
/*
79110
* Postgres and DuckDB have different behavior for the SUBSTRING function when
80111
* the length or offset is negative. This function implements the Postgres
@@ -236,6 +267,12 @@ static void LoadInternal(DatabaseInstance &instance) {
236267
auto to_date_function = ScalarFunction("to_date", {LogicalType::DOUBLE}, LogicalType::DATE, ToDateScalarFun);
237268
ExtensionUtil::RegisterFunction(instance, to_date_function);
238269

270+
auto acosh_function = ScalarFunction("acosh_pg", {LogicalType::DOUBLE}, LogicalType::DOUBLE, AcoshPG);
271+
ExtensionUtil::RegisterFunction(instance, acosh_function);
272+
273+
auto atanh_function = ScalarFunction("atanh_pg", {LogicalType::DOUBLE}, LogicalType::DOUBLE, AtanhPG);
274+
ExtensionUtil::RegisterFunction(instance, atanh_function);
275+
239276
auto nullify_any_type = ScalarFunction("nullify_any_type", {LogicalType::ANY}, LogicalType::SQLNULL, NullifyAnyType);
240277
ExtensionUtil::RegisterFunction(instance, nullify_any_type);
241278

pg_lake_engine/pg_lake_engine--3.0--3.1.sql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ CREATE FUNCTION __lake__internal__nsp__.to_hex(bytea)
1616
IMMUTABLE PARALLEL SAFE STRICT
1717
AS 'MODULE_PATHNAME', $function$pg_lake_internal_dummy_function$function$;
1818

19+
CREATE FUNCTION __lake__internal__nsp__.acosh_pg(double precision)
20+
RETURNS double precision
21+
LANGUAGE C
22+
IMMUTABLE PARALLEL SAFE STRICT
23+
AS 'MODULE_PATHNAME', $function$pg_lake_internal_dummy_function$function$;
24+
25+
CREATE FUNCTION __lake__internal__nsp__.atanh_pg(double precision)
26+
RETURNS double precision
27+
LANGUAGE C
28+
IMMUTABLE PARALLEL SAFE STRICT
29+
AS 'MODULE_PATHNAME', $function$pg_lake_internal_dummy_function$function$;
30+
1931
CREATE FUNCTION __lake__internal__nsp__.from_hex(text)
2032
RETURNS bytea
2133
LANGUAGE C

pg_lake_engine/src/pgduck/rewrite_query.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ static Node *RewriteFuncExprArrayLength(Node *node, void *context);
163163
static Node *RewriteFuncExprPostgisBytea(Node *node, void *context);
164164
static Node *RewriteFuncExprTrigonometry(Node *node, void *context);
165165
static Node *RewriteFuncExprInverseTrigonometry(Node *node, void *context);
166+
static Node *RewriteFuncExprHyperbolic(Node *node, void *context);
166167
static Node *RewriteFuncExprJsonbArrayLength(Node *node, void *context);
167168
static Node *RewriteFuncExprEncode(Node *node, void *context);
168169
static Node *RewriteFuncExprDecode(Node *node, void *context);
@@ -283,6 +284,14 @@ static FunctionCallRewriteRuleByName BuiltinFunctionCallRewriteRulesByName[] =
283284
"pg_catalog", "tand", RewriteFuncExprTrigonometry, 0
284285
},
285286

287+
/* hyperbolic functions */
288+
{
289+
"pg_catalog", "acosh", RewriteFuncExprHyperbolic, 0
290+
},
291+
{
292+
"pg_catalog", "atanh", RewriteFuncExprHyperbolic, 0
293+
},
294+
286295
/* explicit calls to cast functions */
287296
{
288297
"pg_catalog", "bool", RewriteFuncExprCast, 0
@@ -2187,6 +2196,38 @@ RewriteFuncExprInverseTrigonometry(Node *node, void *context)
21872196
}
21882197

21892198

2199+
/*
2200+
* RewriteFuncExprHyperbolic rewrites acosh(..) and atanh(...) function calls
2201+
* into acosh_pg(..) and atanh_pg(..) function calls.
2202+
*/
2203+
static Node *
2204+
RewriteFuncExprHyperbolic(Node *node, void *context)
2205+
{
2206+
FuncExpr *funcExpr = castNode(FuncExpr, node);
2207+
List *funcName;
2208+
2209+
switch (funcExpr->funcid)
2210+
{
2211+
case F_ACOSH:
2212+
funcName = list_make2(makeString(PG_LAKE_INTERNAL_NSP), makeString("acosh_pg"));
2213+
break;
2214+
2215+
case F_ATANH:
2216+
funcName = list_make2(makeString(PG_LAKE_INTERNAL_NSP), makeString("atanh_pg"));
2217+
break;
2218+
2219+
default:
2220+
elog(ERROR, "unexpected function ID in rewrite %d", funcExpr->funcid);
2221+
}
2222+
2223+
Oid argTypes[] = {FLOAT8OID};
2224+
int argCount = 1;
2225+
funcExpr->funcid = LookupFuncName(funcName, argCount, argTypes, false);
2226+
2227+
return (Node *) funcExpr;
2228+
}
2229+
2230+
21902231
/*
21912232
* RewriteFuncExprPostgisBytea rewrites bytea(geometry) function calls into
21922233
* ST_AsWKB(..) function calls to push down (implicit) casts.

pg_lake_engine/src/pgduck/shippable_builtin_functions.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,11 @@ static const PGDuckShippableFunction ShippableBuiltinProcs[] =
346346
{"tan", 'f', 1, {"float8"}, NULL},
347347
{"tand", 'f', 1, {"float8"}, NULL},
348348

349+
/* Hyperbolic functions */
350+
{"asinh", 'f', 1, {"float8"}, NULL},
351+
{"acosh", 'f', 1, {"float8"}, NULL},
352+
{"atanh", 'f', 1, {"float8"}, NULL},
353+
349354
/* array functions */
350355
{"array_append", 'f', 2, {"anycompatiblearray", "anycompatible"}, NULL},
351356
{"array_cat", 'f', 2, {"anycompatiblearray", "anycompatiblearray"}, NULL},

pg_lake_spatial/tests/pytests/test_internal_schema.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ def test_internal_schema(
2121
""",
2222
pg_conn,
2323
)[0][0]
24-
assert result == 61
24+
assert result == 63
2525

2626
pg_conn.rollback()

pg_lake_table/tests/pytests/test_mathematical_functions_pushdown.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,24 @@
145145
"tan(radians(",
146146
True,
147147
),
148+
(
149+
"asinh",
150+
"WHERE col_double > 1 and abs(asinh(col_double) - 0.9503469) < 0.001",
151+
"asinh(",
152+
True,
153+
),
154+
(
155+
"acosh",
156+
"WHERE col_double > 1 and abs(acosh(col_double) - 0.4435682) < 0.001",
157+
"acosh_pg(",
158+
True,
159+
),
160+
(
161+
"atanh",
162+
"WHERE abs(col_double)<1 and abs(atanh(col_double) - 0.6183813) < 0.001",
163+
"atanh_pg(",
164+
True,
165+
),
148166
]
149167

150168

0 commit comments

Comments
 (0)