[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:
linrrarity authored and GitHub committed 2026-05-30 23:45:36 +08:00
1 parent 6e5198b7ce
commit 487f783334
3 files changed
+27 -4

No files matched your search

@@ -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);")