deltacat 2.0.0b9__py3-none-any.whl → 2.0.0b10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- deltacat/__init__.py +27 -6
- deltacat/api.py +478 -123
- deltacat/aws/s3u.py +2 -2
- deltacat/benchmarking/conftest.py +1 -1
- deltacat/catalog/main/impl.py +12 -6
- deltacat/catalog/model/catalog.py +65 -47
- deltacat/catalog/model/properties.py +1 -3
- deltacat/compute/__init__.py +14 -0
- deltacat/compute/converter/constants.py +5 -0
- deltacat/compute/converter/converter_session.py +78 -36
- deltacat/compute/converter/model/convert_input.py +24 -4
- deltacat/compute/converter/model/convert_result.py +61 -0
- deltacat/compute/converter/model/converter_session_params.py +52 -10
- deltacat/compute/converter/pyiceberg/overrides.py +181 -62
- deltacat/compute/converter/steps/convert.py +84 -36
- deltacat/compute/converter/steps/dedupe.py +25 -4
- deltacat/compute/converter/utils/convert_task_options.py +42 -13
- deltacat/compute/converter/utils/iceberg_columns.py +5 -0
- deltacat/compute/converter/utils/io.py +82 -11
- deltacat/compute/converter/utils/s3u.py +13 -4
- deltacat/compute/jobs/__init__.py +0 -0
- deltacat/compute/jobs/client.py +404 -0
- deltacat/constants.py +4 -4
- deltacat/daft/daft_scan.py +7 -3
- deltacat/daft/translator.py +126 -0
- deltacat/examples/basic_logging.py +5 -3
- deltacat/examples/hello_world.py +4 -2
- deltacat/examples/indexer/__init__.py +0 -0
- deltacat/examples/indexer/aws/__init__.py +0 -0
- deltacat/examples/indexer/gcp/__init__.py +0 -0
- deltacat/examples/indexer/indexer.py +163 -0
- deltacat/examples/indexer/job_runner.py +199 -0
- deltacat/io/__init__.py +13 -0
- deltacat/io/dataset/__init__.py +0 -0
- deltacat/io/dataset/deltacat_dataset.py +91 -0
- deltacat/io/datasink/__init__.py +0 -0
- deltacat/io/datasink/deltacat_datasink.py +207 -0
- deltacat/io/datasource/__init__.py +0 -0
- deltacat/io/datasource/deltacat_datasource.py +580 -0
- deltacat/io/reader/__init__.py +0 -0
- deltacat/io/reader/deltacat_read_api.py +172 -0
- deltacat/storage/__init__.py +2 -0
- deltacat/storage/model/expression/__init__.py +47 -0
- deltacat/storage/model/expression/expression.py +656 -0
- deltacat/storage/model/expression/visitor.py +248 -0
- deltacat/storage/model/metafile.py +74 -42
- deltacat/storage/model/scan/push_down.py +32 -5
- deltacat/storage/model/types.py +5 -3
- deltacat/storage/rivulet/__init__.py +4 -4
- deltacat/tests/_io/reader/__init__.py +0 -0
- deltacat/tests/_io/reader/test_deltacat_read_api.py +0 -0
- deltacat/tests/compute/converter/test_convert_session.py +209 -46
- deltacat/tests/local_deltacat_storage/__init__.py +1 -0
- deltacat/tests/storage/model/test_expression.py +327 -0
- deltacat/tests/storage/rivulet/fs/test_file_location_provider.py +2 -1
- deltacat/tests/storage/rivulet/test_dataset.py +1 -1
- deltacat/tests/storage/rivulet/test_manifest.py +1 -1
- deltacat/tests/storage/rivulet/writer/test_memtable_dataset_writer.py +1 -1
- deltacat/tests/test_deltacat_api.py +50 -9
- deltacat/types/media.py +141 -43
- deltacat/types/tables.py +35 -7
- deltacat/utils/daft.py +2 -2
- deltacat/utils/filesystem.py +39 -9
- deltacat/utils/polars.py +128 -0
- deltacat/utils/pyarrow.py +151 -15
- deltacat/utils/ray_utils/concurrency.py +1 -1
- deltacat/utils/ray_utils/runtime.py +56 -4
- deltacat/utils/url.py +1284 -0
- {deltacat-2.0.0b9.dist-info → deltacat-2.0.0b10.dist-info}/METADATA +9 -6
- {deltacat-2.0.0b9.dist-info → deltacat-2.0.0b10.dist-info}/RECORD +73 -48
- {deltacat-2.0.0b9.dist-info → deltacat-2.0.0b10.dist-info}/LICENSE +0 -0
- {deltacat-2.0.0b9.dist-info → deltacat-2.0.0b10.dist-info}/WHEEL +0 -0
- {deltacat-2.0.0b9.dist-info → deltacat-2.0.0b10.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,656 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from abc import ABC
|
4
|
+
from dataclasses import dataclass, field
|
5
|
+
from typing import List, TypeVar, Any
|
6
|
+
|
7
|
+
import pyarrow as pa
|
8
|
+
|
9
|
+
from deltacat.storage.model.schema import FieldName
|
10
|
+
|
11
|
+
|
12
|
+
R = TypeVar("R")
|
13
|
+
C = TypeVar("C")
|
14
|
+
|
15
|
+
|
16
|
+
@dataclass(frozen=True)
|
17
|
+
class Expression(ABC):
|
18
|
+
"""
|
19
|
+
This abstract class serves as the foundation for all expression types
|
20
|
+
in the Deltacat expression tree. It defines common functionality and structure
|
21
|
+
for expressions.
|
22
|
+
"""
|
23
|
+
|
24
|
+
def __str__(self) -> str:
|
25
|
+
"""Convert the expression to a string representation.
|
26
|
+
|
27
|
+
Returns:
|
28
|
+
str: A string representation of the expression.
|
29
|
+
"""
|
30
|
+
from deltacat.storage.model.expression.visitor import DisplayVisitor
|
31
|
+
|
32
|
+
return DisplayVisitor().visit(self, None)
|
33
|
+
|
34
|
+
|
35
|
+
@dataclass(frozen=True)
|
36
|
+
class UnaryExpression(Expression, ABC):
|
37
|
+
"""
|
38
|
+
This abstract class represents operations that work on a single input
|
39
|
+
expression (e.g., NOT, IS NULL).
|
40
|
+
|
41
|
+
Args:
|
42
|
+
operand: The expression this unary operation applies to.
|
43
|
+
"""
|
44
|
+
|
45
|
+
operand: Expression
|
46
|
+
|
47
|
+
@classmethod
|
48
|
+
def of(cls, operand: Expression | Any) -> UnaryExpression:
|
49
|
+
"""
|
50
|
+
Create a new instance with the given operand.
|
51
|
+
|
52
|
+
Args:
|
53
|
+
operand: The expression or value to use as the operand.
|
54
|
+
If not an Expression, it will be converted to a Literal.
|
55
|
+
|
56
|
+
Returns:
|
57
|
+
UnaryExpression: A new instance of this unary expression.
|
58
|
+
"""
|
59
|
+
operand_expr = (
|
60
|
+
operand if isinstance(operand, Expression) else Literal(pa.scalar(operand))
|
61
|
+
)
|
62
|
+
return cls(operand_expr)
|
63
|
+
|
64
|
+
|
65
|
+
@dataclass(frozen=True)
|
66
|
+
class BinaryExpression(Expression, ABC):
|
67
|
+
"""
|
68
|
+
This abstract class represents operations that work on two input
|
69
|
+
expressions (e.g., AND, OR, comparison operators).
|
70
|
+
|
71
|
+
Args:
|
72
|
+
left: The left operand expression.
|
73
|
+
right: The right operand expression.
|
74
|
+
"""
|
75
|
+
|
76
|
+
left: Expression
|
77
|
+
right: Expression
|
78
|
+
|
79
|
+
def with_left(self, left: Expression) -> BinaryExpression:
|
80
|
+
"""
|
81
|
+
Create a new expression with a different left operand.
|
82
|
+
|
83
|
+
Args:
|
84
|
+
left: The new left operand expression.
|
85
|
+
|
86
|
+
Returns:
|
87
|
+
BinaryExpression: A new binary expression with the updated left operand.
|
88
|
+
"""
|
89
|
+
return type(self)(left, self.right)
|
90
|
+
|
91
|
+
def with_right(self, right: Expression) -> BinaryExpression:
|
92
|
+
"""
|
93
|
+
Create a new expression with a different right operand.
|
94
|
+
|
95
|
+
Args:
|
96
|
+
right: The new right operand expression.
|
97
|
+
|
98
|
+
Returns:
|
99
|
+
BinaryExpression: A new binary expression with the updated right operand.
|
100
|
+
"""
|
101
|
+
return type(self)(self.left, right)
|
102
|
+
|
103
|
+
@classmethod
|
104
|
+
def of(cls, left: Expression | Any, right: Expression | Any) -> BinaryExpression:
|
105
|
+
"""
|
106
|
+
Create a new instance with the given operands.
|
107
|
+
|
108
|
+
Args:
|
109
|
+
left: The left operand expression or value.
|
110
|
+
If not an Expression, it will be converted to a Literal.
|
111
|
+
right: The right operand expression or value.
|
112
|
+
If not an Expression, it will be converted to a Literal.
|
113
|
+
|
114
|
+
Returns:
|
115
|
+
BinaryExpression: A new instance of this binary expression.
|
116
|
+
"""
|
117
|
+
left_expr = left if isinstance(left, Expression) else Literal(pa.scalar(left))
|
118
|
+
right_expr = (
|
119
|
+
right if isinstance(right, Expression) else Literal(pa.scalar(right))
|
120
|
+
)
|
121
|
+
return cls(left_expr, right_expr)
|
122
|
+
|
123
|
+
|
124
|
+
@dataclass(frozen=True)
|
125
|
+
class BooleanExpression(Expression, ABC):
|
126
|
+
"""
|
127
|
+
This abstract class represents expressions that produce a boolean
|
128
|
+
value when evaluated, such as comparisons, logical operations, etc.
|
129
|
+
"""
|
130
|
+
|
131
|
+
def and_(self, other: BooleanExpression | Any) -> BooleanExpression:
|
132
|
+
"""
|
133
|
+
Combine this expression with another using logical AND.
|
134
|
+
|
135
|
+
Args:
|
136
|
+
other: The expression to AND with this one.
|
137
|
+
If not a BooleanExpression, it will be converted to a Literal.
|
138
|
+
|
139
|
+
Returns:
|
140
|
+
BooleanExpression: A new AND expression.
|
141
|
+
"""
|
142
|
+
other_expr = (
|
143
|
+
other if isinstance(other, BooleanExpression) else Literal(pa.scalar(other))
|
144
|
+
)
|
145
|
+
return And(self, other_expr)
|
146
|
+
|
147
|
+
def or_(self, other: BooleanExpression | Any) -> BooleanExpression:
|
148
|
+
"""
|
149
|
+
Combine this expression with another using logical OR.
|
150
|
+
|
151
|
+
Args:
|
152
|
+
other: The expression to OR with this one.
|
153
|
+
If not a BooleanExpression, it will be converted to a Literal.
|
154
|
+
|
155
|
+
Returns:
|
156
|
+
BooleanExpression: A new OR expression.
|
157
|
+
"""
|
158
|
+
other_expr = (
|
159
|
+
other if isinstance(other, BooleanExpression) else Literal(pa.scalar(other))
|
160
|
+
)
|
161
|
+
return Or(self, other_expr)
|
162
|
+
|
163
|
+
def not_(self) -> BooleanExpression:
|
164
|
+
"""
|
165
|
+
Negate this expression with logical NOT.
|
166
|
+
|
167
|
+
Returns:
|
168
|
+
BooleanExpression: A new NOT expression.
|
169
|
+
"""
|
170
|
+
return Not(self)
|
171
|
+
|
172
|
+
|
173
|
+
@dataclass(frozen=True)
|
174
|
+
class Reference(Expression):
|
175
|
+
"""
|
176
|
+
This class represents a reference to a column or field in a dataset.
|
177
|
+
|
178
|
+
TODO: Add validation and deltacat schema binding.
|
179
|
+
|
180
|
+
Args:
|
181
|
+
field: The field name of the referenced field.
|
182
|
+
index: Optional index value for the field in the schema.
|
183
|
+
"""
|
184
|
+
|
185
|
+
field: FieldName
|
186
|
+
index: int | None = None
|
187
|
+
|
188
|
+
@classmethod
|
189
|
+
def of(cls, field: FieldName) -> Reference:
|
190
|
+
"""
|
191
|
+
Create a new reference.
|
192
|
+
|
193
|
+
Args:
|
194
|
+
field: The field name of a Deltacat field.
|
195
|
+
|
196
|
+
Returns:
|
197
|
+
Reference: A new reference expression.
|
198
|
+
"""
|
199
|
+
return cls(field)
|
200
|
+
|
201
|
+
def eq(self, other: Expression | Any) -> Equal:
|
202
|
+
"""
|
203
|
+
Create an equality comparison with this reference.
|
204
|
+
|
205
|
+
Args:
|
206
|
+
other: The expression or value to compare with.
|
207
|
+
If not an Expression, it will be converted to a Literal.
|
208
|
+
|
209
|
+
Returns:
|
210
|
+
Equal: A new equality comparison expression.
|
211
|
+
"""
|
212
|
+
if not isinstance(other, Expression):
|
213
|
+
other = Literal(pa.scalar(other))
|
214
|
+
return Equal(self, other)
|
215
|
+
|
216
|
+
def ne(self, other: Expression | Any) -> NotEqual:
|
217
|
+
"""
|
218
|
+
Create an inequality comparison with this reference.
|
219
|
+
|
220
|
+
Args:
|
221
|
+
other: The expression or value to compare with.
|
222
|
+
If not an Expression, it will be converted to a Literal.
|
223
|
+
|
224
|
+
Returns:
|
225
|
+
NotEqual: A new inequality comparison expression.
|
226
|
+
"""
|
227
|
+
if not isinstance(other, Expression):
|
228
|
+
other = Literal(pa.scalar(other))
|
229
|
+
return NotEqual(self, other)
|
230
|
+
|
231
|
+
def gt(self, other: Expression | Any) -> GreaterThan:
|
232
|
+
"""
|
233
|
+
Create a greater than comparison with this reference.
|
234
|
+
|
235
|
+
Args:
|
236
|
+
other: The expression or value to compare with.
|
237
|
+
If not an Expression, it will be converted to a Literal.
|
238
|
+
|
239
|
+
Returns:
|
240
|
+
GreaterThan: A new greater than comparison expression.
|
241
|
+
"""
|
242
|
+
if not isinstance(other, Expression):
|
243
|
+
other = Literal(pa.scalar(other))
|
244
|
+
return GreaterThan(self, other)
|
245
|
+
|
246
|
+
def lt(self, other: Expression | Any) -> LessThan:
|
247
|
+
"""
|
248
|
+
Create a less than comparison with this reference.
|
249
|
+
|
250
|
+
Args:
|
251
|
+
other: The expression or value to compare with.
|
252
|
+
If not an Expression, it will be converted to a Literal.
|
253
|
+
|
254
|
+
Returns:
|
255
|
+
LessThan: A new less than comparison expression.
|
256
|
+
"""
|
257
|
+
if not isinstance(other, Expression):
|
258
|
+
other = Literal(pa.scalar(other))
|
259
|
+
return LessThan(self, other)
|
260
|
+
|
261
|
+
def ge(self, other: Expression | Any) -> GreaterThanEqual:
|
262
|
+
"""
|
263
|
+
Create a greater than or equal comparison with this reference.
|
264
|
+
|
265
|
+
Args:
|
266
|
+
other: The expression or value to compare with.
|
267
|
+
If not an Expression, it will be converted to a Literal.
|
268
|
+
|
269
|
+
Returns:
|
270
|
+
GreaterThanEqual: A new greater than or equal comparison expression.
|
271
|
+
"""
|
272
|
+
if not isinstance(other, Expression):
|
273
|
+
other = Literal(pa.scalar(other))
|
274
|
+
return GreaterThanEqual(self, other)
|
275
|
+
|
276
|
+
def le(self, other: Expression | Any) -> LessThanEqual:
|
277
|
+
"""
|
278
|
+
Create a less than or equal comparison with this reference.
|
279
|
+
|
280
|
+
Args:
|
281
|
+
other: The expression or value to compare with.
|
282
|
+
If not an Expression, it will be converted to a Literal.
|
283
|
+
|
284
|
+
Returns:
|
285
|
+
LessThanEqual: A new less than or equal comparison expression.
|
286
|
+
"""
|
287
|
+
if not isinstance(other, Expression):
|
288
|
+
other = Literal(pa.scalar(other))
|
289
|
+
return LessThanEqual(self, other)
|
290
|
+
|
291
|
+
def is_null(self) -> IsNull:
|
292
|
+
"""
|
293
|
+
Create an IS NULL check for this reference.
|
294
|
+
|
295
|
+
Returns:
|
296
|
+
IsNull: A new IS NULL expression.
|
297
|
+
"""
|
298
|
+
return IsNull(self)
|
299
|
+
|
300
|
+
def in_(self, values: List[Expression | Any]) -> In:
|
301
|
+
"""
|
302
|
+
Create an IN check for this reference.
|
303
|
+
|
304
|
+
Args:
|
305
|
+
values: List of expressions or values to check against.
|
306
|
+
Non-Expression values will be converted to Literals.
|
307
|
+
|
308
|
+
Returns:
|
309
|
+
In: A new IN expression.
|
310
|
+
"""
|
311
|
+
expr_values = [
|
312
|
+
v if isinstance(v, Expression) else Literal(pa.scalar(v)) for v in values
|
313
|
+
]
|
314
|
+
return In(self, expr_values)
|
315
|
+
|
316
|
+
def between(self, lower: Expression | Any, upper: Expression | Any) -> Between:
|
317
|
+
"""
|
318
|
+
Create a BETWEEN check for this reference.
|
319
|
+
|
320
|
+
Args:
|
321
|
+
lower: The lower bound expression or value.
|
322
|
+
If not an Expression, it will be converted to a Literal.
|
323
|
+
upper: The upper bound expression or value.
|
324
|
+
If not an Expression, it will be converted to a Literal.
|
325
|
+
|
326
|
+
Returns:
|
327
|
+
Between: A new BETWEEN expression.
|
328
|
+
"""
|
329
|
+
lower_expr = (
|
330
|
+
lower if isinstance(lower, Expression) else Literal(pa.scalar(lower))
|
331
|
+
)
|
332
|
+
upper_expr = (
|
333
|
+
upper if isinstance(upper, Expression) else Literal(pa.scalar(upper))
|
334
|
+
)
|
335
|
+
return Between(self, lower_expr, upper_expr)
|
336
|
+
|
337
|
+
def like(self, pattern: str | Expression) -> Like:
|
338
|
+
"""
|
339
|
+
Create a LIKE pattern match for this reference.
|
340
|
+
|
341
|
+
Args:
|
342
|
+
pattern: The pattern to match against.
|
343
|
+
If not an Expression, it will be converted to a Literal.
|
344
|
+
|
345
|
+
Returns:
|
346
|
+
Like: A new LIKE expression.
|
347
|
+
"""
|
348
|
+
pattern_expr = (
|
349
|
+
pattern if isinstance(pattern, Expression) else Literal(pa.scalar(pattern))
|
350
|
+
)
|
351
|
+
return Like(self, pattern_expr)
|
352
|
+
|
353
|
+
|
354
|
+
@dataclass(frozen=True)
|
355
|
+
class Literal(Expression):
|
356
|
+
"""
|
357
|
+
Literal value using PyArrow scalar.
|
358
|
+
|
359
|
+
TODO: implement custom deltacat types and literals.
|
360
|
+
|
361
|
+
Args:
|
362
|
+
value: The PyArrow scalar value.
|
363
|
+
"""
|
364
|
+
|
365
|
+
value: pa.Scalar
|
366
|
+
|
367
|
+
@classmethod
|
368
|
+
def of(cls, value: Any) -> Literal:
|
369
|
+
"""
|
370
|
+
Create a new literal value.
|
371
|
+
|
372
|
+
Args:
|
373
|
+
value: The value to create a literal for.
|
374
|
+
If not a PyArrow Scalar, it will be converted.
|
375
|
+
|
376
|
+
Returns:
|
377
|
+
Literal: A new literal expression.
|
378
|
+
"""
|
379
|
+
if not isinstance(value, pa.Scalar):
|
380
|
+
value = pa.scalar(value)
|
381
|
+
return cls(value)
|
382
|
+
|
383
|
+
def eq(self, other: Expression | Any) -> Equal:
|
384
|
+
"""
|
385
|
+
Create an equality comparison with this literal.
|
386
|
+
|
387
|
+
Args:
|
388
|
+
other: The expression or value to compare with.
|
389
|
+
If not an Expression, it will be converted to a Literal.
|
390
|
+
|
391
|
+
Returns:
|
392
|
+
Equal: A new equality comparison expression.
|
393
|
+
"""
|
394
|
+
if not isinstance(other, Expression):
|
395
|
+
other = Literal(pa.scalar(other))
|
396
|
+
return Equal(self, other)
|
397
|
+
|
398
|
+
def ne(self, other: Expression | Any) -> NotEqual:
|
399
|
+
"""
|
400
|
+
Create an inequality comparison with this literal.
|
401
|
+
|
402
|
+
Args:
|
403
|
+
other: The expression or value to compare with.
|
404
|
+
If not an Expression, it will be converted to a Literal.
|
405
|
+
|
406
|
+
Returns:
|
407
|
+
NotEqual: A new inequality comparison expression.
|
408
|
+
"""
|
409
|
+
if not isinstance(other, Expression):
|
410
|
+
other = Literal(pa.scalar(other))
|
411
|
+
return NotEqual(self, other)
|
412
|
+
|
413
|
+
|
414
|
+
@dataclass(frozen=True)
|
415
|
+
class Equal(BinaryExpression, BooleanExpression):
|
416
|
+
"""
|
417
|
+
Equality comparison (=).
|
418
|
+
|
419
|
+
Args:
|
420
|
+
left: The left operand expression.
|
421
|
+
right: The right operand expression.
|
422
|
+
"""
|
423
|
+
|
424
|
+
pass
|
425
|
+
|
426
|
+
|
427
|
+
@dataclass(frozen=True)
|
428
|
+
class NotEqual(BinaryExpression, BooleanExpression):
|
429
|
+
"""
|
430
|
+
Inequality comparison (<>).
|
431
|
+
|
432
|
+
Args:
|
433
|
+
left: The left operand expression.
|
434
|
+
right: The right operand expression.
|
435
|
+
"""
|
436
|
+
|
437
|
+
pass
|
438
|
+
|
439
|
+
|
440
|
+
@dataclass(frozen=True)
|
441
|
+
class GreaterThan(BinaryExpression, BooleanExpression):
|
442
|
+
"""
|
443
|
+
Greater than comparison (>).
|
444
|
+
|
445
|
+
Args:
|
446
|
+
left: The left operand expression.
|
447
|
+
right: The right operand expression.
|
448
|
+
"""
|
449
|
+
|
450
|
+
pass
|
451
|
+
|
452
|
+
|
453
|
+
@dataclass(frozen=True)
|
454
|
+
class LessThan(BinaryExpression, BooleanExpression):
|
455
|
+
"""
|
456
|
+
Less than comparison (<).
|
457
|
+
|
458
|
+
Args:
|
459
|
+
left: The left operand expression.
|
460
|
+
right: The right operand expression.
|
461
|
+
"""
|
462
|
+
|
463
|
+
pass
|
464
|
+
|
465
|
+
|
466
|
+
@dataclass(frozen=True)
|
467
|
+
class GreaterThanEqual(BinaryExpression, BooleanExpression):
|
468
|
+
"""
|
469
|
+
Greater than or equal comparison (>=).
|
470
|
+
|
471
|
+
Args:
|
472
|
+
left: The left operand expression.
|
473
|
+
right: The right operand expression.
|
474
|
+
"""
|
475
|
+
|
476
|
+
pass
|
477
|
+
|
478
|
+
|
479
|
+
@dataclass(frozen=True)
|
480
|
+
class LessThanEqual(BinaryExpression, BooleanExpression):
|
481
|
+
"""
|
482
|
+
Less than or equal comparison (<=).
|
483
|
+
|
484
|
+
Args:
|
485
|
+
left: The left operand expression.
|
486
|
+
right: The right operand expression.
|
487
|
+
"""
|
488
|
+
|
489
|
+
pass
|
490
|
+
|
491
|
+
|
492
|
+
@dataclass(frozen=True)
|
493
|
+
class And(BinaryExpression, BooleanExpression):
|
494
|
+
"""
|
495
|
+
Logical AND operation.
|
496
|
+
|
497
|
+
Args:
|
498
|
+
left: The left operand expression.
|
499
|
+
right: The right operand expression.
|
500
|
+
"""
|
501
|
+
|
502
|
+
pass
|
503
|
+
|
504
|
+
|
505
|
+
@dataclass(frozen=True)
|
506
|
+
class Or(BinaryExpression, BooleanExpression):
|
507
|
+
"""
|
508
|
+
Logical OR operation.
|
509
|
+
|
510
|
+
Args:
|
511
|
+
left: The left operand expression.
|
512
|
+
right: The right operand expression.
|
513
|
+
"""
|
514
|
+
|
515
|
+
pass
|
516
|
+
|
517
|
+
|
518
|
+
@dataclass(frozen=True)
|
519
|
+
class Not(UnaryExpression, BooleanExpression):
|
520
|
+
"""
|
521
|
+
Logical NOT operation.
|
522
|
+
|
523
|
+
Args:
|
524
|
+
operand: The boolean expression to negate.
|
525
|
+
"""
|
526
|
+
|
527
|
+
operand: BooleanExpression
|
528
|
+
|
529
|
+
|
530
|
+
@dataclass(frozen=True)
|
531
|
+
class In(BooleanExpression):
|
532
|
+
"""
|
533
|
+
Checks if a value is in a list of values.
|
534
|
+
|
535
|
+
Args:
|
536
|
+
value: The expression to check.
|
537
|
+
values: List of expressions to check against.
|
538
|
+
"""
|
539
|
+
|
540
|
+
value: Expression
|
541
|
+
values: List[Expression] = field(default_factory=list)
|
542
|
+
|
543
|
+
@classmethod
|
544
|
+
def of(cls, value: Expression | Any, values: List[Expression | Any]) -> In:
|
545
|
+
"""
|
546
|
+
Create a new IN expression.
|
547
|
+
|
548
|
+
Args:
|
549
|
+
value: The expression or value to check.
|
550
|
+
If not an Expression, it will be converted to a Literal.
|
551
|
+
values: List of expressions or values to check against.
|
552
|
+
Non-Expression values will be converted to Literals.
|
553
|
+
|
554
|
+
Returns:
|
555
|
+
In: A new IN expression.
|
556
|
+
"""
|
557
|
+
value_expr = (
|
558
|
+
value if isinstance(value, Expression) else Literal(pa.scalar(value))
|
559
|
+
)
|
560
|
+
value_exprs = [
|
561
|
+
v if isinstance(v, Expression) else Literal(pa.scalar(v)) for v in values
|
562
|
+
]
|
563
|
+
return cls(value_expr, value_exprs)
|
564
|
+
|
565
|
+
|
566
|
+
@dataclass(frozen=True)
|
567
|
+
class Between(BooleanExpression):
|
568
|
+
"""
|
569
|
+
Checks if a value is between two other values (inclusive).
|
570
|
+
|
571
|
+
Args:
|
572
|
+
value: The expression to check.
|
573
|
+
lower: The lower bound expression.
|
574
|
+
upper: The upper bound expression.
|
575
|
+
"""
|
576
|
+
|
577
|
+
value: Expression
|
578
|
+
lower: Expression
|
579
|
+
upper: Expression
|
580
|
+
|
581
|
+
@classmethod
|
582
|
+
def of(
|
583
|
+
cls, value: Expression | Any, lower: Expression | Any, upper: Expression | Any
|
584
|
+
) -> Between:
|
585
|
+
"""
|
586
|
+
Create a new BETWEEN expression.
|
587
|
+
|
588
|
+
Args:
|
589
|
+
value: The expression or value to check.
|
590
|
+
If not an Expression, it will be converted to a Literal.
|
591
|
+
lower: The lower bound expression or value.
|
592
|
+
If not an Expression, it will be converted to a Literal.
|
593
|
+
upper: The upper bound expression or value.
|
594
|
+
If not an Expression, it will be converted to a Literal.
|
595
|
+
|
596
|
+
Returns:
|
597
|
+
Between: A new BETWEEN expression.
|
598
|
+
"""
|
599
|
+
value_expr = (
|
600
|
+
value if isinstance(value, Expression) else Literal(pa.scalar(value))
|
601
|
+
)
|
602
|
+
lower_expr = (
|
603
|
+
lower if isinstance(lower, Expression) else Literal(pa.scalar(lower))
|
604
|
+
)
|
605
|
+
upper_expr = (
|
606
|
+
upper if isinstance(upper, Expression) else Literal(pa.scalar(upper))
|
607
|
+
)
|
608
|
+
return cls(value_expr, lower_expr, upper_expr)
|
609
|
+
|
610
|
+
|
611
|
+
@dataclass(frozen=True)
|
612
|
+
class Like(BooleanExpression):
|
613
|
+
"""
|
614
|
+
Pattern matching for string values.
|
615
|
+
|
616
|
+
Args:
|
617
|
+
value: The expression to check.
|
618
|
+
pattern: The pattern to match against.
|
619
|
+
"""
|
620
|
+
|
621
|
+
value: Expression
|
622
|
+
pattern: Expression
|
623
|
+
|
624
|
+
@classmethod
|
625
|
+
def of(cls, value: Expression | Any, pattern: Expression | Any) -> Like:
|
626
|
+
"""
|
627
|
+
Create a new LIKE expression.
|
628
|
+
|
629
|
+
Args:
|
630
|
+
value: The expression or value to check.
|
631
|
+
If not an Expression, it will be converted to a Literal.
|
632
|
+
pattern: The pattern expression or value to match against.
|
633
|
+
If not an Expression, it will be converted to a Literal.
|
634
|
+
|
635
|
+
Returns:
|
636
|
+
Like: A new LIKE expression.
|
637
|
+
"""
|
638
|
+
value_expr = (
|
639
|
+
value if isinstance(value, Expression) else Literal(pa.scalar(value))
|
640
|
+
)
|
641
|
+
pattern_expr = (
|
642
|
+
pattern if isinstance(pattern, Expression) else Literal(pa.scalar(pattern))
|
643
|
+
)
|
644
|
+
return cls(value_expr, pattern_expr)
|
645
|
+
|
646
|
+
|
647
|
+
@dataclass(frozen=True)
|
648
|
+
class IsNull(UnaryExpression, BooleanExpression):
|
649
|
+
"""
|
650
|
+
Checks if a value is NULL.
|
651
|
+
|
652
|
+
Args:
|
653
|
+
operand: The expression to check for NULL.
|
654
|
+
"""
|
655
|
+
|
656
|
+
pass
|