mirror of
https://github.com/apache/doris.git
synced 2026-11-04 07:31:17 +00:00
[Enhancement](udf) Do not check file when inline code exists (#63906)
Before this change, even when inline code was present, the FE would still attempt to parse and validate the `FILE` in the `CREATE FUNCTION` statement. However, during subsequent execution, even if `FILE` is valid, it would not be used. Therefore, when inline code is present, we can omit checking the `FILE` field when creating the table. before ```sql DROP FUNCTION IF EXISTS py_inline_file_udf(INT); CREATE FUNCTION py_inline_file_udf(INT) RETURNS INT PROPERTIES ( "type"="PYTHON_UDF", "file"="http://127.0.0.1:12345/non_existent.zip", "symbol"="evaluate", "runtime_version"="3.12.11", "always_nullable"="true" ) AS $$ def evaluate(x): if x is None: return None return x + 100 $$; SELECT py_inline_file_udf(val) FROM t_repro ORDER BY id; -- errCode = 2, detailMessage = cannot to compute object's checksum. ``` now ```sql Doris> SELECT py_inline_file_udf(val) FROM t_repro ORDER BY id; +-------------------------+ | py_inline_file_udf(val) | +-------------------------+ | 110 | | 120 | | 130 | +-------------------------+ ```
This commit is contained in:
1 parent
6e5198b7ce
commit
487f783334
3 files changed
+27
-4
No files matched your search
+3
-4
@@ -330,11 +330,10 @@ public class CreateFunctionCommand extends Command implements ForwardWithSync {
|
||||
|
||||
userFile = properties.getOrDefault(FILE_KEY, properties.get(OBJECT_FILE_KEY));
|
||||
originalUserFile = userFile; // Keep original jar name for BE
|
||||
// Convert userFile to realUrl only for FE checksum calculation
|
||||
if (!Strings.isNullOrEmpty(userFile) && binaryType != Function.BinaryType.RPC) {
|
||||
// Inline Python code is authoritative. Keep FILE in metadata for replay, but do not load or validate it here.
|
||||
if (Strings.isNullOrEmpty(functionCode) && !Strings.isNullOrEmpty(userFile)
|
||||
&& binaryType != Function.BinaryType.RPC) {
|
||||
userFile = getRealUrl(userFile);
|
||||
}
|
||||
if (!Strings.isNullOrEmpty(userFile) && binaryType != Function.BinaryType.RPC) {
|
||||
try {
|
||||
computeObjectChecksum();
|
||||
} catch (IOException | NoSuchAlgorithmException e) {
|
||||
|
||||
@@ -20,3 +20,5 @@ true
|
||||
3 30 31 python p****n
|
||||
4 40 41 doris d***s
|
||||
|
||||
-- !select_file_inline_precedence --
|
||||
1007
|
||||
@@ -117,6 +117,28 @@ suite("test_pythonudf_file_protocol") {
|
||||
FROM file_protocol_test_table
|
||||
ORDER BY id;
|
||||
"""
|
||||
|
||||
// Inline code must take precedence over FILE. Use a missing FILE path so the
|
||||
// test fails if FE or BE tries to validate/load it as a module.
|
||||
sql """ DROP FUNCTION IF EXISTS py_file_inline_precedence(INT); """
|
||||
sql """
|
||||
CREATE FUNCTION py_file_inline_precedence(INT)
|
||||
RETURNS INT
|
||||
PROPERTIES (
|
||||
"type" = "PYTHON_UDF",
|
||||
"file" = "file://${context.file.parent}/udf_scripts/missing_inline_precedence.zip",
|
||||
"symbol" = "evaluate",
|
||||
"runtime_version" = "${runtime_version}"
|
||||
)
|
||||
AS \$\$
|
||||
def evaluate(arg):
|
||||
if arg is None:
|
||||
return None
|
||||
return int(arg + 1000)
|
||||
\$\$;
|
||||
"""
|
||||
|
||||
qt_select_file_inline_precedence """ SELECT py_file_inline_precedence(7) AS result; """
|
||||
|
||||
} finally {
|
||||
try_sql("DROP FUNCTION IF EXISTS py_file_int_add(INT);")
|
||||
|
||||
Reference in new issue
Block a user