0
# Expression Operations and Operators
1
2
The `ImplicitExpressionOperations` trait provides a rich set of operations for building and manipulating expressions using natural Scala syntax with operator overloading.
3
4
## Core Operations Trait
5
6
```scala { .api }
7
trait ImplicitExpressionOperations {
8
private[flink] def expr: Expression
9
10
// Field aliasing with symbols
11
def as(name: Symbol, extraNames: Symbol*): Expression
12
13
// Comparison operators
14
def >(other: Expression): Expression
15
def >=(other: Expression): Expression
16
def <(other: Expression): Expression
17
def <=(other: Expression): Expression
18
def ===(other: Expression): Expression
19
def !==(other: Expression): Expression
20
21
// Logical operators
22
def &&(other: Expression): Expression
23
def ||(other: Expression): Expression
24
def unary_!: Expression
25
26
// Arithmetic operators
27
def +(other: Expression): Expression
28
def -(other: Expression): Expression
29
def *(other: Expression): Expression
30
def /(other: Expression): Expression
31
def %(other: Expression): Expression
32
def unary_-: Expression
33
def unary_+: Expression
34
35
// Specialized operations
36
def to(other: Expression): Expression
37
def ?(ifTrue: Expression, ifFalse: Expression): Expression
38
def rows: Expression
39
}
40
```
41
42
## Field Aliasing
43
44
### Symbol-Based Aliasing
45
46
```scala { .api }
47
def as(name: Symbol, extraNames: Symbol*): Expression
48
```
49
50
Usage examples:
51
```scala
52
import org.apache.flink.table.api._
53
54
// Single alias
55
val aliased = $"price" * 1.1 as 'totalPrice
56
57
// Multiple aliases (for expressions that expand to multiple fields)
58
val multiAlias = someComplexExpression as ('field1, 'field2, 'field3)
59
```
60
61
The trait also inherits string-based aliasing from the base implementation:
62
```scala
63
// String-based aliasing (inherited)
64
val stringAlias = $"price" * 1.1 as "totalPrice"
65
```
66
67
## Comparison Operations
68
69
### Relational Operators
70
71
```scala { .api }
72
def >(other: Expression): Expression // Greater than
73
def >=(other: Expression): Expression // Greater than or equal
74
def <(other: Expression): Expression // Less than
75
def <=(other: Expression): Expression // Less than or equal
76
def ===(other: Expression): Expression // Equal (use === to avoid conflicts)
77
def !==(other: Expression): Expression // Not equal
78
```
79
80
Usage examples:
81
```scala
82
// Numeric comparisons
83
val condition1 = $"age" > lit(18)
84
val condition2 = $"salary" >= lit(50000.0)
85
val condition3 = $"score" < lit(100)
86
val condition4 = $"rating" <= lit(5.0)
87
88
// Equality comparisons
89
val isActive = $"status" === lit("ACTIVE")
90
val notDeleted = $"deleted" !== lit(true)
91
92
// String comparisons
93
val nameFilter = $"name" === lit("John")
94
95
// Date comparisons
96
val recentOrders = $"orderDate" > lit(LocalDate.now().minusDays(30))
97
```
98
99
## Logical Operations
100
101
### Boolean Operators
102
103
```scala { .api }
104
def &&(other: Expression): Expression // Logical AND
105
def ||(other: Expression): Expression // Logical OR
106
def unary_!: Expression // Logical NOT
107
```
108
109
Usage examples:
110
```scala
111
// Complex conditions
112
val adultActive = ($"age" >= lit(18)) && ($"status" === lit("ACTIVE"))
113
val eligibleUser = ($"premium" === lit(true)) || ($"trialExpiry" > currentDate())
114
val nonDeleted = !($"deleted" === lit(true))
115
116
// Chained logical operations
117
val complexFilter = ($"category" === lit("ELECTRONICS")) &&
118
(($"price" > lit(100)) || ($"discount" > lit(0.2))) &&
119
!($"outOfStock" === lit(true))
120
```
121
122
## Arithmetic Operations
123
124
### Mathematical Operators
125
126
```scala { .api }
127
def +(other: Expression): Expression // Addition
128
def -(other: Expression): Expression // Subtraction
129
def *(other: Expression): Expression // Multiplication
130
def /(other: Expression): Expression // Division
131
def %(other: Expression): Expression // Modulo
132
def unary_-: Expression // Negation
133
def unary_+: Expression // Positive (identity)
134
```
135
136
Usage examples:
137
```scala
138
// Basic arithmetic
139
val totalPrice = $"price" + $"tax"
140
val discount = $"originalPrice" - $"finalPrice"
141
val area = $"width" * $"height"
142
val average = $"sum" / $"count"
143
val remainder = $"value" % lit(10)
144
145
// Unary operations
146
val negated = -$"balance"
147
val positive = +$"amount"
148
149
// Complex calculations
150
val finalAmount = ($"price" * $"quantity") +
151
($"price" * $"quantity" * $"taxRate") -
152
$"discount"
153
154
// Mathematical expressions with literals
155
val adjustedScore = ($"score" * lit(1.1)) + lit(5.0)
156
```
157
158
## Specialized Operations
159
160
### Range Expression
161
162
```scala { .api }
163
def to(other: Expression): Expression
164
```
165
166
Creates a range expression for column selection:
167
168
```scala
169
// Select columns from 'start' to 'end'
170
val columnRange = $"col1" to $"col5" // Selects col1, col2, col3, col4, col5
171
172
// Usage in select
173
val result = table.select(columnRange)
174
```
175
176
### Ternary Conditional
177
178
```scala { .api }
179
def ?(ifTrue: Expression, ifFalse: Expression): Expression
180
```
181
182
Provides ternary conditional operator:
183
184
```scala
185
// Conditional expressions
186
val status = ($"age" >= lit(18)) ? lit("Adult") : lit("Minor")
187
val category = ($"score" > lit(80)) ? lit("High") :
188
(($"score" > lit(60)) ? lit("Medium") : lit("Low"))
189
190
// Null handling
191
val displayName = $"nickname".isNotNull ? $"nickname" : $"firstName"
192
193
// Numeric conditionals
194
val finalPrice = ($"memberType" === lit("PREMIUM")) ?
195
($"price" * lit(0.9)) : $"price"
196
```
197
198
### Row Interval
199
200
```scala { .api }
201
def rows: Expression
202
```
203
204
Creates row interval for windowing operations:
205
206
```scala
207
// Window with row-based bounds
208
val windowSpec = Over
209
.partitionBy($"userId")
210
.orderBy($"timestamp")
211
.preceding(lit(5).rows) // 5 rows preceding
212
.currentRow()
213
214
// Usage in window function
215
val result = table.select(
216
$"*",
217
$"amount".sum.over(windowSpec) as "runningSum"
218
)
219
```
220
221
## Complex Expression Examples
222
223
### Nested Conditional Logic
224
225
```scala
226
// Multi-level conditionals
227
val priorityLevel = ($"urgent" === lit(true)) ? lit("HIGH") :
228
(($"important" === lit(true)) ? lit("MEDIUM") : lit("LOW"))
229
230
// Combining with arithmetic
231
val adjustedPrice = ($"customerType" === lit("VIP")) ?
232
($"price" * lit(0.8)) :
233
(($"customerType" === lit("MEMBER")) ?
234
($"price" * lit(0.9)) : $"price")
235
```
236
237
### Complex Filtering
238
239
```scala
240
// Advanced filtering conditions
241
val eligibleCustomers = table.filter(
242
($"age" >= lit(18)) &&
243
($"creditScore" > lit(650)) &&
244
(($"income" > lit(50000)) || ($"assets" > lit(100000))) &&
245
!($"blacklisted" === lit(true))
246
)
247
```
248
249
### Mathematical Computations
250
251
```scala
252
// Complex mathematical expressions
253
val distanceFormula = (($"x2" - $"x1") * ($"x2" - $"x1")) +
254
(($"y2" - $"y1") * ($"y2" - $"y1"))
255
256
val normalizedScore = ($"rawScore" - $"minScore") /
257
($"maxScore" - $"minScore")
258
259
// Statistical calculations
260
val zScore = ($"value" - $"mean") / $"standardDeviation"
261
```
262
263
### String and Date Operations
264
265
```scala
266
// String operations (when combined with built-in functions)
267
val fullName = concat($"firstName", lit(" "), $"lastName")
268
val emailDomain = substring($"email", position($"email", lit("@")) + lit(1))
269
270
// Date arithmetic
271
val daysSinceOrder = currentDate() - $"orderDate"
272
val futureDate = $"startDate" + interval(lit(30), DAY)
273
```
274
275
## Type Safety and Compatibility
276
277
### Expression Type Preservation
278
279
Operations maintain proper type information:
280
281
```scala
282
val intResult: Expression = $"intField" + lit(5) // Type: INT
283
val doubleResult: Expression = $"price" * lit(1.1) // Type: DOUBLE
284
val stringResult: Expression = $"name" + lit(" Jr.") // Type: STRING
285
val boolResult: Expression = $"age" > lit(18) // Type: BOOLEAN
286
```
287
288
### Null Handling
289
290
All operations handle null values according to SQL semantics:
291
292
```scala
293
// Null-safe operations
294
val safeAdd = $"nullableField" + lit(10) // null + 10 = null
295
val safeCompare = $"nullableField" > lit(5) // null > 5 = null
296
val safeLogical = $"boolField" && lit(true) // null && true = null
297
```
298
299
### Automatic Type Coercion
300
301
Compatible types are automatically coerced:
302
303
```scala
304
val intDouble = $"intField" + lit(3.14) // int + double = double
305
val intLong = $"intField" + lit(100L) // int + long = long
306
val numericString = $"price" + lit(" USD") // double + string = string
307
```
308
309
## Performance Considerations
310
311
### Expression Optimization
312
313
- Expressions are optimized during query planning
314
- Constant folding applied to literal operations
315
- Common subexpression elimination
316
- Predicate pushdown for filter conditions
317
318
### Lazy Evaluation
319
320
- Operations build expression trees without immediate evaluation
321
- Actual computation occurs during query execution
322
- Allows for query optimization opportunities
323
324
### Memory Efficiency
325
326
- Expression objects are lightweight wrappers
327
- No intermediate results stored during expression building
328
- Memory usage scales with expression complexity, not data size
329
330
## Best Practices
331
332
### Readable Complex Expressions
333
334
```scala
335
// Break complex expressions into readable parts
336
val isEligibleAge = $"age" >= lit(18)
337
val hasGoodCredit = $"creditScore" > lit(650)
338
val hasIncome = $"income" > lit(30000)
339
340
val eligibleCustomer = isEligibleAge && hasGoodCredit && hasIncome
341
```
342
343
### Consistent Null Handling
344
345
```scala
346
// Explicit null checks when needed
347
val safeCalculation = $"value".isNotNull ?
348
($"value" * lit(1.1)) :
349
lit(0.0)
350
```
351
352
### Type-Aware Operations
353
354
```scala
355
// Use appropriate literal types
356
val intOp = $"intField" + lit(5) // lit(5) creates INT literal
357
val doubleOp = $"doubleField" + lit(5.0) // lit(5.0) creates DOUBLE literal
358
val stringOp = $"textField" + lit("suffix") // lit("suffix") creates STRING literal
359
```