Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(udf): change JS UDF to include the function head #20392

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions e2e_test/streaming/nexmark/sinks/q14.slt.part
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
statement ok
CREATE FUNCTION count_char(s varchar, c varchar) RETURNS int LANGUAGE javascript AS $$
export function count_char(s, c) {
var count = 0;
for (var cc of s) {
if (cc === c) {
count++;
}
}
return count;
}
$$;

statement ok
Expand Down
2 changes: 2 additions & 0 deletions e2e_test/streaming/nexmark/views/q14.slt.part
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
statement ok
CREATE FUNCTION count_char(s varchar, c varchar) RETURNS int LANGUAGE javascript AS $$
export function count_char(s, c) {
var count = 0;
for (var cc of s) {
if (cc === c) {
count++;
}
}
return count;
}
$$;

statement ok
Expand Down
29 changes: 29 additions & 0 deletions e2e_test/udf/js_udf.slt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
statement ok
create function int_42() returns int language javascript as $$
export function int_42() {
return 42;
}
$$;

query I
Expand All @@ -14,6 +16,7 @@ drop function int_42;

statement ok
create function gcd(a int, b int) returns int language javascript as $$
export function gcd(a, b) {
// required before we support `RETURNS NULL ON NULL INPUT`
if(a == null || b == null) {
return null;
Expand All @@ -24,6 +27,7 @@ create function gcd(a int, b int) returns int language javascript as $$
a = t;
}
return a;
}
$$;

query I
Expand All @@ -37,7 +41,9 @@ drop function gcd;

statement ok
create function decimal_add(a decimal, b decimal) returns decimal language javascript as $$
export function decimal_add(a, b) {
return a + b;
}
$$;

query R
Expand All @@ -51,7 +57,9 @@ drop function decimal_add;

statement ok
create function to_string(a boolean, b smallint, c int, d bigint, e real, f float, g decimal, h varchar, i bytea, j jsonb) returns varchar language javascript as $$
export function to_string(a, b, c, d, e, f, g, h, i, j) {
return a.toString() + b.toString() + c.toString() + d.toString() + e.toString() + f.toString() + g.toString() + h.toString() + i.toString() + JSON.stringify(j);
}
$$;

query T
Expand All @@ -66,6 +74,7 @@ drop function to_string;
# show data types in javascript
statement ok
create function js_typeof(a boolean, b smallint, c int, d bigint, e real, f float, g decimal, h varchar, i bytea, j jsonb) returns jsonb language javascript as $$
export function js_typeof(a, b, c, d, e, f, g, h, i, j) {
return {
boolean: typeof a,
smallint: typeof b,
Expand All @@ -78,6 +87,7 @@ create function js_typeof(a boolean, b smallint, c int, d bigint, e real, f floa
bytea: typeof i,
jsonb: typeof j,
};
}
$$;

query T
Expand All @@ -93,7 +103,9 @@ statement ok
create function return_all(a boolean, b smallint, c int, d bigint, e real, f float, g decimal, h varchar, i bytea, j jsonb, s struct<f1 int, f2 int>)
returns struct<a boolean, b smallint, c int, d bigint, e real, f float, g decimal, h varchar, i bytea, j jsonb, s struct<f1 int, f2 int>>
language javascript as $$
export function return_all(a, b, c, d, e, f, g, h, i, j, s) {
return {a,b,c,d,e,f,g,h,i,j,s};
}
$$;

query T
Expand All @@ -119,9 +131,11 @@ drop function return_all;

statement ok
create function series(n int) returns table (x int) language javascript as $$
export function series(n) {
for(let i = 0; i < n; i++) {
yield i;
}
}
$$;

query I
Expand All @@ -139,9 +153,11 @@ drop function series;

statement ok
create function split(s varchar) returns table (word varchar, length int) language javascript as $$
export function split(s) {
for(let word of s.split(' ')) {
yield { word: word, length: word.length };
}
}
$$;

query IT
Expand Down Expand Up @@ -235,3 +251,16 @@ drop function weighted_avg;

statement ok
drop aggregate weighted_avg;

statement ok
create function int_42_legacy() returns int language javascript as $$
return 42;
$$;

query I
select int_42_legacy();
----
42

statement ok
drop function int_42_legacy;
31 changes: 21 additions & 10 deletions src/expr/impl/src/udf/quickjs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,30 @@ static QUICKJS: UdfImplDescriptor = UdfImplDescriptor {
opts.body.context("body is required")?,
)?;
} else {
let body = format!(
"export function{} {}({}) {{ {} }}",
if opts.kind.is_table() { "*" } else { "" },
opts.identifier,
opts.arg_names.join(","),
opts.body.context("body is required")?,
);
runtime.add_function(
let res = runtime.add_function(
opts.identifier,
UdfArrowConvert::default().to_arrow_field("", opts.return_type)?,
CallMode::CalledOnNullInput,
&body,
)?;
opts.body.context("body is required")?,
);

if res.is_err() {
// COMPATIBILITY: This is for keeping compatible with the legacy syntax that
// only function body is provided by users.
let body = format!(
"export function{} {}({}) {{ {} }}",
if opts.kind.is_table() { "*" } else { "" },
opts.identifier,
opts.arg_names.join(","),
opts.body.context("body is required")?,
);
runtime.add_function(
opts.identifier,
UdfArrowConvert::default().to_arrow_field("", opts.return_type)?,
CallMode::CalledOnNullInput,
&body,
)?;
}
}
Ok(Box::new(QuickJsFunction {
runtime,
Expand Down
Loading