Skip to content

Commit cbb4760

Browse files
authored
feat(query): Enhanced UDF Functionality with IMMUTABLE Support (#18369)
* feat(query): Enhanced UDF Functionality with IMMUTABLE Support * fix * fix tests
1 parent ab5e31d commit cbb4760

File tree

30 files changed

+464
-143
lines changed

30 files changed

+464
-143
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/meta/app/src/principal/user_defined_function.rs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub struct UDFServer {
3535
pub language: String,
3636
pub arg_types: Vec<DataType>,
3737
pub return_type: DataType,
38+
pub immutable: Option<bool>,
3839
}
3940

4041
#[derive(Clone, Debug, Eq, PartialEq)]
@@ -47,6 +48,7 @@ pub struct UDFScript {
4748
pub arg_types: Vec<DataType>,
4849
pub return_type: DataType,
4950
pub runtime_version: String,
51+
pub immutable: Option<bool>,
5052
}
5153

5254
#[derive(Clone, Debug, Eq, PartialEq)]
@@ -135,6 +137,7 @@ impl UserDefinedFunction {
135137
arg_types: Vec<DataType>,
136138
return_type: DataType,
137139
description: &str,
140+
immutable: Option<bool>,
138141
) -> Self {
139142
Self {
140143
name: name.to_string(),
@@ -146,6 +149,7 @@ impl UserDefinedFunction {
146149
language: language.to_string(),
147150
arg_types,
148151
return_type,
152+
immutable,
149153
}),
150154
created_on: Utc::now(),
151155
}
@@ -160,6 +164,7 @@ impl UserDefinedFunction {
160164
return_type: DataType,
161165
runtime_version: &str,
162166
description: &str,
167+
immutable: Option<bool>,
163168
) -> Self {
164169
Self {
165170
name: name.to_string(),
@@ -173,6 +178,7 @@ impl UserDefinedFunction {
173178
runtime_version: runtime_version.to_string(),
174179
imports: vec![],
175180
packages: vec![],
181+
immutable,
176182
}),
177183
created_on: Utc::now(),
178184
}
@@ -202,17 +208,23 @@ impl Display for UDFDefinition {
202208
handler,
203209
headers,
204210
language,
211+
immutable,
205212
}) => {
206213
for (i, item) in arg_types.iter().enumerate() {
207214
if i > 0 {
208215
write!(f, ", ")?;
209216
}
210217
write!(f, "{item}")?;
211218
}
212-
write!(
213-
f,
214-
") RETURNS {return_type} LANGUAGE {language} HANDLER = {handler}"
215-
)?;
219+
write!(f, ") RETURNS {return_type} LANGUAGE {language}")?;
220+
if let Some(immutable) = immutable {
221+
if *immutable {
222+
write!(f, " IMMUTABLE")?;
223+
} else {
224+
write!(f, " VOLATILE")?;
225+
}
226+
}
227+
write!(f, " HANDLER = {handler}")?;
216228
if !headers.is_empty() {
217229
write!(f, " HEADERS = (")?;
218230
for (i, (key, value)) in headers.iter().enumerate() {
@@ -234,16 +246,25 @@ impl Display for UDFDefinition {
234246
runtime_version,
235247
imports,
236248
packages,
249+
immutable,
237250
}) => {
238251
for (i, item) in arg_types.iter().enumerate() {
239252
if i > 0 {
240253
write!(f, ", ")?;
241254
}
242255
write!(f, "{item}")?;
243256
}
257+
write!(f, ") RETURNS {return_type} LANGUAGE {language}")?;
258+
if let Some(immutable) = immutable {
259+
if *immutable {
260+
write!(f, " IMMUTABLE")?;
261+
} else {
262+
write!(f, " VOLATILE")?;
263+
}
264+
}
244265
write!(
245266
f,
246-
") RETURNS {return_type} LANGUAGE {language} IMPORTS = {imports:?} PACKAGES = {packages:?} RUNTIME_VERSION = {runtime_version} HANDLER = {handler} AS $${code}$$"
267+
" IMPORTS = {imports:?} PACKAGES = {packages:?} RUNTIME_VERSION = {runtime_version} HANDLER = {handler} AS $${code}$$"
247268
)?;
248269
}
249270
UDFDefinition::UDAFScript(UDAFScript {

src/meta/proto-conv/src/udf_from_to_protobuf_impl.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ impl FromToProto for mt::UDFServer {
7575
handler: p.handler,
7676
headers: p.headers,
7777
language: p.language,
78+
immutable: p.immutable,
7879
})
7980
}
8081

@@ -109,6 +110,7 @@ impl FromToProto for mt::UDFServer {
109110
language: self.language.clone(),
110111
arg_types,
111112
return_type: Some(return_type),
113+
immutable: self.immutable,
112114
})
113115
}
114116
}
@@ -139,6 +141,7 @@ impl FromToProto for mt::UDFScript {
139141
runtime_version: p.runtime_version,
140142
imports: p.imports,
141143
packages: p.packages,
144+
immutable: p.immutable,
142145
})
143146
}
144147

@@ -175,6 +178,7 @@ impl FromToProto for mt::UDFScript {
175178
runtime_version: self.runtime_version.clone(),
176179
imports: self.imports.clone(),
177180
packages: self.packages.clone(),
181+
immutable: self.immutable,
178182
})
179183
}
180184
}

src/meta/proto-conv/src/util.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ const META_CHANGE_LOG: &[(u64, &str)] = &[
164164
(132, "2025-06-25: Remove: SequenceMeta.start"),
165165
(133, "2025-06-25: Add: Add new StageFileCompression Zip"),
166166
(134, "2025-06-27: Add: SequenceMeta.storage_version"),
167+
(135, "2025-07-16: Add: UDFServer.immutable, UDFScript.immutable"),
167168
// Dear developer:
168169
// If you're gonna add a new metadata version, you'll have to add a test for it.
169170
// You could just copy an existing test file(e.g., `../tests/it/v024_table_meta.rs`)

src/meta/proto-conv/tests/it/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,4 @@ mod v131_avro_and_parquet_file_format_params;
126126
mod v132_remove_sequence_meta_start;
127127
mod v133_stage_file_compression;
128128
mod v134_add_sequence_meta_storage_version;
129+
mod v135_udf_immutable;

src/meta/proto-conv/tests/it/proto_conv.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ fn new_udf_server() -> databend_common_meta_app::principal::UDFServer {
305305
language: "python".to_string(),
306306
arg_types: vec![DataType::String],
307307
return_type: DataType::Boolean,
308+
immutable: None,
308309
}
309310
}
310311

src/meta/proto-conv/tests/it/v058_udf.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ fn test_decode_v57_udf() -> anyhow::Result<()> {
6060
DataType::Number(NumberDataType::Int32),
6161
],
6262
return_type: DataType::Number(NumberDataType::Int64),
63+
immutable: None,
6364
}),
6465
created_on: DateTime::<Utc>::default(),
6566
};

src/meta/proto-conv/tests/it/v079_udf_created_on.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ fn test_decode_v79_udf_python() -> anyhow::Result<()> {
6363
DataType::Number(NumberDataType::Int32),
6464
],
6565
return_type: DataType::Number(NumberDataType::Int64),
66+
immutable: None,
6667
}),
6768
created_on: DateTime::<Utc>::from_timestamp(1702603569, 0).unwrap(),
6869
};

src/meta/proto-conv/tests/it/v081_udf_script.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ fn test_decode_v81_udf_python() -> anyhow::Result<()> {
6464
DataType::Number(NumberDataType::Int32),
6565
],
6666
return_type: DataType::Number(NumberDataType::Int64),
67+
immutable: None,
6768
}),
6869
created_on: DateTime::<Utc>::from_timestamp(1702603569, 0).unwrap(),
6970
};
@@ -119,6 +120,7 @@ fn test_decode_udf_script() -> anyhow::Result<()> {
119120
imports: vec![],
120121
packages: vec![],
121122
runtime_version: "3.12.2".to_string(),
123+
immutable: None,
122124
}),
123125
created_on: DateTime::<Utc>::default(),
124126
};

src/meta/proto-conv/tests/it/v124_udf_server_headers.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ fn test_decode_v124_udf_server_headers() -> anyhow::Result<()> {
4949
language: "python".to_string(),
5050
arg_types: vec![DataType::String],
5151
return_type: DataType::Boolean,
52+
immutable: None,
5253
};
5354

5455
common::test_load_old(

0 commit comments

Comments
 (0)