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::ArrayPrepend
176 | Type::FormatType
177 | Type::ArrayDistinct
178 | Type::ArrayMin
179 | Type::ArrayDims
180 | Type::ArrayLength
181 | Type::Cardinality
182 | Type::TrimArray
183 | Type::ArrayRemove
184 | Type::ArrayReplace
185 | Type::ArrayPosition
186 | Type::ArrayContains
187 | Type::ArrayContained
188 | Type::ArrayFlatten
189 | Type::HexToInt256
190 | Type::JsonbConcat
191 | Type::JsonbAccess
192 | Type::JsonbAccessStr
193 | Type::JsonbExtractPath
194 | Type::JsonbExtractPathVariadic
195 | Type::JsonbExtractPathText
196 | Type::JsonbExtractPathTextVariadic
197 | Type::JsonbTypeof
198 | Type::JsonbArrayLength
199 | Type::JsonbObject
200 | Type::JsonbPretty
201 | Type::JsonbDeletePath
202 | Type::JsonbContains
203 | Type::JsonbContained
204 | Type::JsonbExists
205 | Type::JsonbExistsAny
206 | Type::JsonbExistsAll
207 | Type::JsonbStripNulls
208 | Type::JsonbBuildArray
209 | Type::JsonbBuildArrayVariadic
210 | Type::JsonbBuildObject
211 | Type::JsonbPopulateRecord
212 | Type::JsonbToArray
213 | Type::JsonbToRecord
214 | Type::JsonbBuildObjectVariadic
215 | Type::JsonbPathExists
216 | Type::JsonbPathMatch
217 | Type::JsonbPathQueryArray
218 | Type::JsonbPathQueryFirst
219 | Type::JsonbSet
220 | Type::JsonbPopulateMap
221 | Type::IsJson
222 | Type::ToJsonb
223 | Type::Sind
224 | Type::Cosd
225 | Type::Cotd
226 | Type::Asind
227 | Type::Sinh
228 | Type::Cosh
229 | Type::Coth
230 | Type::Tanh
231 | Type::Atanh
232 | Type::Asinh
233 | Type::Acosh
234 | Type::Decode
235 | Type::Encode
236 | Type::GetBit
237 | Type::GetByte
238 | Type::SetBit
239 | Type::SetByte
240 | Type::BitCount
241 | Type::Sha1
242 | Type::Sha224
243 | Type::Sha256
244 | Type::Sha384
245 | Type::Sha512
246 | Type::Hmac
247 | Type::SecureCompare
248 | Type::Decrypt
249 | Type::Encrypt
250 | Type::Tand
251 | Type::ArrayPositions
252 | Type::StringToArray
253 | Type::Format
254 | Type::FormatVariadic
255 | Type::PgwireSend
256 | Type::PgwireRecv
257 | Type::ArrayTransform
258 | Type::Greatest
259 | Type::Least
260 | Type::ConvertFrom
261 | Type::ConvertTo
262 | Type::IcebergTransform
263 | Type::InetNtoa
264 | Type::InetAton
265 | Type::QuoteLiteral
266 | Type::QuoteNullable
267 | Type::MapFromEntries
268 | Type::MapAccess
269 | Type::MapKeys
270 | Type::MapValues
271 | Type::MapEntries
272 | Type::MapFromKeyValues
273 | Type::MapCat
274 | Type::MapContains
275 | Type::MapDelete
276 | Type::MapFilter
277 | Type::MapInsert
278 | Type::MapLength
279 | Type::L2Distance
280 | Type::CosineDistance
281 | Type::L1Distance
282 | Type::InnerProduct
283 | Type::VecConcat
284 | Type::L2Norm
285 | Type::L2Normalize
286 | Type::VnodeUser
287 | Type::RwEpochToTs
288 | Type::CheckNotNull
289 | Type::CompositeCast =>
290 {
292 func_call
293 .inputs()
294 .iter()
295 .for_each(|expr| self.visit_expr(expr));
296 }
297 Type::Vnode | Type::TestFeature
300 | Type::License
301 | Type::Proctime
302 | Type::PgSleep
303 | Type::PgSleepFor
304 | Type::PgSleepUntil
305 | Type::CastRegclass
306 | Type::PgGetIndexdef
307 | Type::ColDescription
308 | Type::PgGetViewdef
309 | Type::PgGetUserbyid
310 | Type::PgIndexesSize
311 | Type::PgRelationSize
312 | Type::PgGetSerialSequence
313 | Type::PgIndexColumnHasProperty
314 | Type::HasTablePrivilege
315 | Type::HasAnyColumnPrivilege
316 | Type::HasSchemaPrivilege
317 | Type::MakeTimestamptz
318 | Type::PgIsInRecovery
319 | Type::RwRecoveryStatus
320 | Type::PgTableIsVisible
321 | Type::HasFunctionPrivilege
322 | Type::OpenaiEmbedding
323 | Type::HasDatabasePrivilege
324 | Type::Random => self.impure = true,
325 }
326 }
327}
328
329pub fn is_pure(expr: &ExprImpl) -> bool {
330 !is_impure(expr)
331}
332
333pub fn is_impure(expr: &ExprImpl) -> bool {
334 let mut a = ImpureAnalyzer::default();
335 a.visit_expr(expr);
336 a.impure
337}
338
339pub fn is_impure_func_call(func_call: &FunctionCall) -> bool {
340 let mut a = ImpureAnalyzer::default();
341 a.visit_function_call(func_call);
342 a.impure
343}
344
345#[cfg(test)]
346mod tests {
347 use risingwave_common::types::DataType;
348 use risingwave_pb::expr::expr_node::Type;
349
350 use crate::expr::{ExprImpl, FunctionCall, InputRef, is_impure, is_pure};
351
352 fn expect_pure(expr: &ExprImpl) {
353 assert!(is_pure(expr));
354 assert!(!is_impure(expr));
355 }
356
357 fn expect_impure(expr: &ExprImpl) {
358 assert!(!is_pure(expr));
359 assert!(is_impure(expr));
360 }
361
362 #[test]
363 fn test_pure_funcs() {
364 let e: ExprImpl = FunctionCall::new(
365 Type::Add,
366 vec![
367 InputRef::new(0, DataType::Int16).into(),
368 InputRef::new(0, DataType::Int16).into(),
369 ],
370 )
371 .unwrap()
372 .into();
373 expect_pure(&e);
374
375 let e: ExprImpl = FunctionCall::new(
376 Type::GreaterThan,
377 vec![
378 InputRef::new(0, DataType::Timestamptz).into(),
379 FunctionCall::new(Type::Proctime, vec![]).unwrap().into(),
380 ],
381 )
382 .unwrap()
383 .into();
384 expect_impure(&e);
385 }
386}