risingwave_frontend/expr/
pure.rs1use expr_node::Type;
16use risingwave_pb::expr::expr_node;
17
18use super::{ExprImpl, ExprVisitor};
19use crate::expr::FunctionCall;
20
21#[derive(Default)]
22pub(crate) struct ImpureAnalyzer {
23 pub(crate) impure: bool,
24}
25
26impl ExprVisitor for ImpureAnalyzer {
27 fn visit_user_defined_function(&mut self, _func_call: &super::UserDefinedFunction) {
28 self.impure = true;
29 }
30
31 fn visit_now(&mut self, _: &super::Now) {
32 self.impure = true;
33 }
34
35 fn visit_function_call(&mut self, func_call: &super::FunctionCall) {
36 match func_call.func_type() {
37 Type::Unspecified => unreachable!(),
38 Type::Add
39 | Type::Subtract
40 | Type::Multiply
41 | Type::Divide
42 | Type::Modulus
43 | Type::Equal
44 | Type::NotEqual
45 | Type::LessThan
46 | Type::LessThanOrEqual
47 | Type::GreaterThan
48 | Type::GreaterThanOrEqual
49 | Type::And
50 | Type::Or
51 | Type::Not
52 | Type::In
53 | Type::Some
54 | Type::All
55 | Type::BitwiseAnd
56 | Type::BitwiseOr
57 | Type::BitwiseXor
58 | Type::BitwiseNot
59 | Type::BitwiseShiftLeft
60 | Type::BitwiseShiftRight
61 | Type::Extract
62 | Type::DatePart
63 | Type::TumbleStart
64 | Type::SecToTimestamptz
65 | Type::AtTimeZone
66 | Type::DateTrunc
67 | Type::DateBin
68 | Type::MakeDate
69 | Type::MakeTime
70 | Type::MakeTimestamp
71 | Type::CharToTimestamptz
72 | Type::CharToDate
73 | Type::CastWithTimeZone
74 | Type::AddWithTimeZone
75 | Type::SubtractWithTimeZone
76 | Type::Cast
77 | Type::Substr
78 | Type::Length
79 | Type::Like
80 | Type::ILike
81 | Type::SimilarToEscape
82 | Type::Upper
83 | Type::Lower
84 | Type::Trim
85 | Type::Replace
86 | Type::Position
87 | Type::Ltrim
88 | Type::Rtrim
89 | Type::Case
90 | Type::ConstantLookup
91 | Type::RoundDigit
92 | Type::Round
93 | Type::Ascii
94 | Type::Translate
95 | Type::Coalesce
96 | Type::ConcatWs
97 | Type::ConcatWsVariadic
98 | Type::Abs
99 | Type::SplitPart
100 | Type::Ceil
101 | Type::Floor
102 | Type::Trunc
103 | Type::ToChar
104 | Type::Md5
105 | Type::CharLength
106 | Type::Repeat
107 | Type::ConcatOp
108 | Type::ByteaConcatOp
109 | Type::Concat
110 | Type::ConcatVariadic
111 | Type::BoolOut
112 | Type::OctetLength
113 | Type::BitLength
114 | Type::Overlay
115 | Type::RegexpMatch
116 | Type::RegexpReplace
117 | Type::RegexpCount
118 | Type::RegexpSplitToArray
119 | Type::RegexpEq
120 | Type::Pow
121 | Type::Exp
122 | Type::Ln
123 | Type::Log10
124 | Type::Chr
125 | Type::StartsWith
126 | Type::Initcap
127 | Type::Lpad
128 | Type::Rpad
129 | Type::Reverse
130 | Type::Strpos
131 | Type::ToAscii
132 | Type::ToHex
133 | Type::QuoteIdent
134 | Type::Sin
135 | Type::Cos
136 | Type::Tan
137 | Type::Cot
138 | Type::Asin
139 | Type::Acos
140 | Type::Acosd
141 | Type::Atan
142 | Type::Atan2
143 | Type::Atand
144 | Type::Atan2d
145 | Type::Sqrt
146 | Type::Cbrt
147 | Type::Sign
148 | Type::Scale
149 | Type::MinScale
150 | Type::TrimScale
151 | Type::Left
152 | Type::Right
153 | Type::Degrees
154 | Type::Radians
155 | Type::IsTrue
156 | Type::IsNotTrue
157 | Type::IsFalse
158 | Type::IsNotFalse
159 | Type::IsNull
160 | Type::IsNotNull
161 | Type::IsDistinctFrom
162 | Type::IsNotDistinctFrom
163 | Type::Neg
164 | Type::Field
165 | Type::Array
166 | Type::ArrayAccess
167 | Type::ArrayRangeAccess
168 | Type::Row
169 | Type::ArrayToString
170 | Type::ArrayCat
171 | Type::ArrayMax
172 | Type::ArraySum
173 | Type::ArraySort
174 | Type::ArrayAppend
175 | Type::ArrayReverse
176 | Type::ArrayPrepend
177 | Type::FormatType
178 | Type::ArrayDistinct
179 | Type::ArrayMin
180 | Type::ArrayDims
181 | Type::ArrayLength
182 | Type::Cardinality
183 | Type::TrimArray
184 | Type::ArrayRemove
185 | Type::ArrayReplace
186 | Type::ArrayPosition
187 | Type::ArrayContains
188 | Type::ArrayContained
189 | Type::ArrayFlatten
190 | Type::HexToInt256
191 | Type::JsonbConcat
192 | Type::JsonbAccess
193 | Type::JsonbAccessStr
194 | Type::JsonbExtractPath
195 | Type::JsonbExtractPathVariadic
196 | Type::JsonbExtractPathText
197 | Type::JsonbExtractPathTextVariadic
198 | Type::JsonbTypeof
199 | Type::JsonbArrayLength
200 | Type::JsonbObject
201 | Type::JsonbPretty
202 | Type::JsonbDeletePath
203 | Type::JsonbContains
204 | Type::JsonbContained
205 | Type::JsonbExists
206 | Type::JsonbExistsAny
207 | Type::JsonbExistsAll
208 | Type::JsonbStripNulls
209 | Type::JsonbBuildArray
210 | Type::JsonbBuildArrayVariadic
211 | Type::JsonbBuildObject
212 | Type::JsonbPopulateRecord
213 | Type::JsonbToArray
214 | Type::JsonbToRecord
215 | Type::JsonbBuildObjectVariadic
216 | Type::JsonbPathExists
217 | Type::JsonbPathMatch
218 | Type::JsonbPathQueryArray
219 | Type::JsonbPathQueryFirst
220 | Type::JsonbSet
221 | Type::JsonbPopulateMap
222 | Type::IsJson
223 | Type::ToJsonb
224 | Type::Sind
225 | Type::Cosd
226 | Type::Cotd
227 | Type::Asind
228 | Type::Sinh
229 | Type::Cosh
230 | Type::Coth
231 | Type::Tanh
232 | Type::Atanh
233 | Type::Asinh
234 | Type::Acosh
235 | Type::Decode
236 | Type::Encode
237 | Type::GetBit
238 | Type::GetByte
239 | Type::SetBit
240 | Type::SetByte
241 | Type::BitCount
242 | Type::Sha1
243 | Type::Sha224
244 | Type::Sha256
245 | Type::Sha384
246 | Type::Sha512
247 | Type::Hmac
248 | Type::SecureCompare
249 | Type::Decrypt
250 | Type::Encrypt
251 | Type::Tand
252 | Type::ArrayPositions
253 | Type::StringToArray
254 | Type::Format
255 | Type::FormatVariadic
256 | Type::PgwireSend
257 | Type::PgwireRecv
258 | Type::ArrayTransform
259 | Type::Greatest
260 | Type::Least
261 | Type::ConvertFrom
262 | Type::ConvertTo
263 | Type::IcebergTransform
264 | Type::InetNtoa
265 | Type::InetAton
266 | Type::QuoteLiteral
267 | Type::QuoteNullable
268 | Type::MapFromEntries
269 | Type::MapAccess
270 | Type::MapKeys
271 | Type::MapValues
272 | Type::MapEntries
273 | Type::MapFromKeyValues
274 | Type::MapCat
275 | Type::MapContains
276 | Type::MapDelete
277 | Type::MapFilter
278 | Type::MapInsert
279 | Type::MapLength
280 | Type::L2Distance
281 | Type::CosineDistance
282 | Type::L1Distance
283 | Type::InnerProduct
284 | Type::VecConcat
285 | Type::L2Norm
286 | Type::L2Normalize
287 | Type::Subvector
288 | Type::VnodeUser
289 | Type::RwEpochToTs
290 | Type::CheckNotNull
291 | Type::CompositeCast =>
292 {
294 func_call
295 .inputs()
296 .iter()
297 .for_each(|expr| self.visit_expr(expr));
298 }
299 Type::Vnode | Type::TestFeature
302 | Type::License
303 | Type::Proctime
304 | Type::PgSleep
305 | Type::PgSleepFor
306 | Type::PgSleepUntil
307 | Type::CastRegclass
308 | Type::PgGetIndexdef
309 | Type::ColDescription
310 | Type::PgGetViewdef
311 | Type::PgGetUserbyid
312 | Type::PgIndexesSize
313 | Type::PgRelationSize
314 | Type::PgGetSerialSequence
315 | Type::PgIndexColumnHasProperty
316 | Type::HasTablePrivilege
317 | Type::HasAnyColumnPrivilege
318 | Type::HasSchemaPrivilege
319 | Type::MakeTimestamptz
320 | Type::PgIsInRecovery
321 | Type::RwRecoveryStatus
322 | Type::RwClusterId
323 | Type::RwFragmentVnodes
324 | Type::RwActorVnodes
325 | Type::PgTableIsVisible
326 | Type::HasFunctionPrivilege
327 | Type::OpenaiEmbedding
328 | Type::HasDatabasePrivilege
329 | Type::Random => self.impure = true,
330 }
331 }
332}
333
334pub fn is_pure(expr: &ExprImpl) -> bool {
335 !is_impure(expr)
336}
337
338pub fn is_impure(expr: &ExprImpl) -> bool {
339 let mut a = ImpureAnalyzer::default();
340 a.visit_expr(expr);
341 a.impure
342}
343
344pub fn is_impure_func_call(func_call: &FunctionCall) -> bool {
345 let mut a = ImpureAnalyzer::default();
346 a.visit_function_call(func_call);
347 a.impure
348}
349
350#[cfg(test)]
351mod tests {
352 use risingwave_common::types::DataType;
353 use risingwave_pb::expr::expr_node::Type;
354
355 use crate::expr::{ExprImpl, FunctionCall, InputRef, is_impure, is_pure};
356
357 fn expect_pure(expr: &ExprImpl) {
358 assert!(is_pure(expr));
359 assert!(!is_impure(expr));
360 }
361
362 fn expect_impure(expr: &ExprImpl) {
363 assert!(!is_pure(expr));
364 assert!(is_impure(expr));
365 }
366
367 #[test]
368 fn test_pure_funcs() {
369 let e: ExprImpl = FunctionCall::new(
370 Type::Add,
371 vec![
372 InputRef::new(0, DataType::Int16).into(),
373 InputRef::new(0, DataType::Int16).into(),
374 ],
375 )
376 .unwrap()
377 .into();
378 expect_pure(&e);
379
380 let e: ExprImpl = FunctionCall::new(
381 Type::GreaterThan,
382 vec![
383 InputRef::new(0, DataType::Timestamptz).into(),
384 FunctionCall::new(Type::Proctime, vec![]).unwrap().into(),
385 ],
386 )
387 .unwrap()
388 .into();
389 expect_impure(&e);
390 }
391}