0
# Expression and Conversion System
1
2
The expression and conversion system provides seamless integration between Scala values and Flink expressions through implicit conversions and rich expression creation methods.
3
4
## Core Traits
5
6
### ImplicitExpressionConversions
7
8
Main trait providing implicit conversions from Scala literals to Expression objects and expression creation utilities.
9
10
```scala { .api }
11
trait ImplicitExpressionConversions {
12
// Window operation constants
13
implicit val UNBOUNDED_ROW: Expression
14
implicit val UNBOUNDED_RANGE: Expression
15
implicit val CURRENT_ROW: Expression
16
implicit val CURRENT_RANGE: Expression
17
18
// Field reference creation
19
def $(name: String): Expression
20
def col(name: String): Expression
21
22
// Literal creation
23
def lit(v: Any): Expression
24
def lit(v: Any, dataType: DataType): Expression
25
26
// Function calls
27
def call(path: String, params: Expression*): Expression
28
def call(function: UserDefinedFunction, params: Expression*): Expression
29
def call(function: Class[_ <: UserDefinedFunction], params: Expression*): Expression
30
def callSql(sqlExpression: String): Expression
31
}
32
```
33
34
## Implicit Classes for Expression Wrapping
35
36
### WithOperations
37
38
Adds expression operations to existing Expression objects.
39
40
```scala { .api }
41
implicit class WithOperations(e: Expression) extends ImplicitExpressionOperations {
42
def expr: Expression = e
43
}
44
```
45
46
### UnresolvedFieldExpression
47
48
Creates field expressions from Scala symbols.
49
50
```scala { .api }
51
implicit class UnresolvedFieldExpression(s: Symbol) extends ImplicitExpressionOperations {
52
def expr: Expression = unresolvedRef(s.name)
53
}
54
```
55
56
Usage example:
57
```scala
58
val fieldExpr = 'myField // Creates field reference from symbol
59
```
60
61
### AnyWithOperations
62
63
Generic wrapper for any type with implicit conversion to Expression.
64
65
```scala { .api }
66
implicit class AnyWithOperations[T](e: T)(implicit toExpr: T => Expression)
67
extends ImplicitExpressionOperations {
68
def expr: Expression = toExpr(e)
69
}
70
```
71
72
## Literal Expression Classes
73
74
Specialized implicit classes for primitive types that provide expression operations:
75
76
```scala { .api }
77
implicit class LiteralLongExpression(l: Long) extends ImplicitExpressionOperations
78
implicit class LiteralByteExpression(b: Byte) extends ImplicitExpressionOperations
79
implicit class LiteralShortExpression(s: Short) extends ImplicitExpressionOperations
80
implicit class LiteralIntExpression(i: Int) extends ImplicitExpressionOperations
81
implicit class LiteralFloatExpression(f: Float) extends ImplicitExpressionOperations
82
implicit class LiteralDoubleExpression(d: Double) extends ImplicitExpressionOperations
83
implicit class LiteralStringExpression(str: String) extends ImplicitExpressionOperations
84
implicit class LiteralBooleanExpression(bool: Boolean) extends ImplicitExpressionOperations
85
```
86
87
Usage example:
88
```scala
89
val expr = 42.asInstanceOf[Int] + 10 // Arithmetic operations on literals
90
```
91
92
## Function Call Classes
93
94
### ScalarFunctionCall
95
96
Enables calling scalar functions with expression parameters.
97
98
```scala { .api }
99
implicit class ScalarFunctionCall(scalarFunction: ScalarFunction) {
100
def apply(params: Expression*): Expression
101
}
102
```
103
104
### TableFunctionCall
105
106
Enables calling table functions.
107
108
```scala { .api }
109
implicit class TableFunctionCall(tableFunction: TableFunction[_]) {
110
def apply(params: Expression*): Expression
111
}
112
```
113
114
### ImperativeAggregateFunctionCall
115
116
Enables calling aggregate functions.
117
118
```scala { .api }
119
implicit class ImperativeAggregateFunctionCall(aggregateFunction: ImperativeAggregateFunction[_, _]) {
120
def apply(params: Expression*): Expression
121
}
122
```
123
124
## Field Access
125
126
### String Interpolation for Fields
127
128
```scala { .api }
129
implicit class FieldExpression(sc: StringContext) {
130
def $(args: Any*): Expression // String interpolation: $"fieldName"
131
}
132
```
133
134
Usage examples:
135
```scala
136
$"userId" // Simple field reference
137
$"user.address" // Nested field reference
138
$"items[0].price" // Array element access
139
```
140
141
## Implicit Conversion Functions
142
143
### Primitive Type Conversions
144
145
```scala { .api }
146
implicit def byte2Literal(b: Byte): Expression
147
implicit def short2Literal(s: Short): Expression
148
implicit def int2Literal(i: Int): Expression
149
implicit def long2Literal(l: Long): Expression
150
implicit def double2Literal(d: Double): Expression
151
implicit def float2Literal(f: Float): Expression
152
implicit def string2Literal(str: String): Expression
153
implicit def boolean2Literal(bool: Boolean): Expression
154
implicit def javaByte2Literal(b: JByte): Expression
155
implicit def javaShort2Literal(s: JShort): Expression
156
implicit def javaInt2Literal(i: JInteger): Expression
157
implicit def javaLong2Literal(l: JLong): Expression
158
implicit def javaDouble2Literal(d: JDouble): Expression
159
implicit def javaFloat2Literal(f: JFloat): Expression
160
implicit def javaBoolean2Literal(bool: JBoolean): Expression
161
```
162
163
### Date and Time Conversions
164
165
```scala { .api }
166
implicit def sqlDate2Literal(d: Date): Expression
167
implicit def sqlTime2Literal(t: Time): Expression
168
implicit def sqlTimestamp2Literal(t: Timestamp): Expression
169
implicit def localDate2Literal(d: LocalDate): Expression
170
implicit def localTime2Literal(t: LocalTime): Expression
171
implicit def localDateTime2Literal(dt: LocalDateTime): Expression
172
```
173
174
### Collection Conversions
175
176
```scala { .api }
177
implicit def seq2ArrayConstructor(seq: Seq[Expression]): Expression
178
implicit def map2MapConstructor(map: Map[Expression, Expression]): Expression
179
```
180
181
### Specialized Type Conversions
182
183
```scala { .api }
184
implicit def bigDecimal2Literal(bd: JBigDecimal): Expression
185
implicit def row2Literal(row: Row): Expression
186
implicit def list2ArrayConstructor(list: JList[Expression]): Expression
187
implicit def map2MapConstructor(map: JMap[Expression, Expression]): Expression
188
```
189
190
## Expression Creation Methods
191
192
### Field References
193
194
```scala { .api }
195
def $(name: String): Expression // Create field reference
196
def col(name: String): Expression // Alias for $()
197
```
198
199
### Literals
200
201
```scala { .api }
202
def lit(v: Any): Expression // Create literal from any value
203
def lit(v: Any, dataType: DataType): Expression // Create typed literal
204
```
205
206
### Function Calls
207
208
```scala { .api }
209
def call(path: String, params: Expression*): Expression // Call catalog function
210
def call(function: UserDefinedFunction, params: Expression*): Expression // Call inline function
211
def call(function: Class[_ <: UserDefinedFunction], params: Expression*): Expression // Call UDF class
212
def callSql(sqlExpression: String): Expression // Execute SQL expression
213
```
214
215
## Usage Examples
216
217
### Basic Field and Literal Operations
218
219
```scala
220
import org.apache.flink.table.api._
221
222
// Field references
223
val userId = $"userId"
224
val userField = col("user")
225
226
// Literals
227
val constValue = lit(42)
228
val constString = lit("hello")
229
230
// Mixed operations
231
val result = $"price" * 1.1 + lit(5.0)
232
```
233
234
### Function Calls
235
236
```scala
237
// Built-in function call
238
val upperName = call("UPPER", $"name")
239
240
// User-defined function
241
class MyUDF extends ScalarFunction {
242
def eval(value: String): String = value.toUpperCase
243
}
244
val myUdf = new MyUDF()
245
val result = call(myUdf, $"name")
246
247
// SQL expression
248
val sqlResult = callSql("CURRENT_TIMESTAMP")
249
```
250
251
### Symbol-based Field Access
252
253
```scala
254
// Using symbols for field names (legacy approach)
255
val field1 = 'userId // Equivalent to $"userId"
256
val field2 = 'user_name // Equivalent to $"user_name"
257
```
258
259
### Window Operations
260
261
```scala
262
// Using window constants
263
import org.apache.flink.table.api._
264
265
val windowSpec = Over
266
.partitionBy($"userId")
267
.orderBy($"timestamp")
268
.preceding(UNBOUNDED_RANGE)
269
.following(CURRENT_ROW)
270
```
271
272
### Collection to Expression Conversion
273
274
```scala
275
// Array construction from Scala sequence
276
val items = Seq(lit(1), lit(2), lit(3))
277
val arrayExpr = items // Implicitly converted to array constructor
278
279
// Map construction
280
val mapData = Map(lit("key1") -> lit("value1"), lit("key2") -> lit("value2"))
281
val mapExpr = mapData // Implicitly converted to map constructor
282
```
283
284
## Type Safety Considerations
285
286
The implicit conversion system maintains type safety through:
287
288
1. **Compile-time Checking**: Implicit conversions are resolved at compile time
289
2. **Expression Type Preservation**: Operations maintain proper expression types
290
3. **Generic Type Support**: Full support for parameterized types like `Option[T]`
291
4. **Macro Integration**: Seamless integration with type information macros
292
293
## Performance Notes
294
295
- Implicit conversions have zero runtime overhead after compilation
296
- Expression objects are lightweight wrappers around Flink's internal representation
297
- Complex expressions are lazily evaluated during query execution
298
- Field references are resolved during query planning phase