pixeltable 0.3.2__py3-none-any.whl → 0.3.3__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.
Potentially problematic release.
This version of pixeltable might be problematic. Click here for more details.
- pixeltable/__init__.py +64 -11
- pixeltable/__version__.py +2 -2
- pixeltable/catalog/__init__.py +1 -1
- pixeltable/catalog/catalog.py +50 -27
- pixeltable/catalog/column.py +27 -11
- pixeltable/catalog/dir.py +6 -4
- pixeltable/catalog/globals.py +8 -1
- pixeltable/catalog/insertable_table.py +22 -12
- pixeltable/catalog/named_function.py +10 -6
- pixeltable/catalog/path.py +3 -2
- pixeltable/catalog/path_dict.py +8 -6
- pixeltable/catalog/schema_object.py +2 -1
- pixeltable/catalog/table.py +121 -101
- pixeltable/catalog/table_version.py +291 -142
- pixeltable/catalog/table_version_path.py +8 -5
- pixeltable/catalog/view.py +67 -26
- pixeltable/dataframe.py +102 -72
- pixeltable/env.py +20 -21
- pixeltable/exec/__init__.py +2 -2
- pixeltable/exec/aggregation_node.py +10 -4
- pixeltable/exec/cache_prefetch_node.py +5 -3
- pixeltable/exec/component_iteration_node.py +9 -8
- pixeltable/exec/data_row_batch.py +21 -10
- pixeltable/exec/exec_context.py +10 -3
- pixeltable/exec/exec_node.py +23 -12
- pixeltable/exec/expr_eval/evaluators.py +13 -7
- pixeltable/exec/expr_eval/expr_eval_node.py +24 -15
- pixeltable/exec/expr_eval/globals.py +30 -7
- pixeltable/exec/expr_eval/row_buffer.py +5 -6
- pixeltable/exec/expr_eval/schedulers.py +151 -31
- pixeltable/exec/in_memory_data_node.py +8 -7
- pixeltable/exec/row_update_node.py +15 -5
- pixeltable/exec/sql_node.py +56 -27
- pixeltable/exprs/__init__.py +2 -2
- pixeltable/exprs/arithmetic_expr.py +57 -26
- pixeltable/exprs/array_slice.py +1 -1
- pixeltable/exprs/column_property_ref.py +2 -1
- pixeltable/exprs/column_ref.py +20 -15
- pixeltable/exprs/comparison.py +6 -2
- pixeltable/exprs/compound_predicate.py +1 -3
- pixeltable/exprs/data_row.py +2 -2
- pixeltable/exprs/expr.py +101 -72
- pixeltable/exprs/expr_dict.py +2 -1
- pixeltable/exprs/expr_set.py +3 -1
- pixeltable/exprs/function_call.py +39 -41
- pixeltable/exprs/globals.py +1 -0
- pixeltable/exprs/in_predicate.py +2 -2
- pixeltable/exprs/inline_expr.py +20 -17
- pixeltable/exprs/json_mapper.py +4 -2
- pixeltable/exprs/json_path.py +12 -18
- pixeltable/exprs/literal.py +5 -9
- pixeltable/exprs/method_ref.py +1 -0
- pixeltable/exprs/object_ref.py +1 -1
- pixeltable/exprs/row_builder.py +32 -17
- pixeltable/exprs/rowid_ref.py +14 -5
- pixeltable/exprs/similarity_expr.py +11 -6
- pixeltable/exprs/sql_element_cache.py +1 -1
- pixeltable/exprs/type_cast.py +24 -9
- pixeltable/ext/__init__.py +1 -0
- pixeltable/ext/functions/__init__.py +1 -0
- pixeltable/ext/functions/whisperx.py +2 -2
- pixeltable/ext/functions/yolox.py +11 -11
- pixeltable/func/aggregate_function.py +17 -13
- pixeltable/func/callable_function.py +6 -6
- pixeltable/func/expr_template_function.py +15 -14
- pixeltable/func/function.py +16 -16
- pixeltable/func/function_registry.py +11 -8
- pixeltable/func/globals.py +4 -2
- pixeltable/func/query_template_function.py +12 -13
- pixeltable/func/signature.py +18 -9
- pixeltable/func/tools.py +10 -17
- pixeltable/func/udf.py +106 -11
- pixeltable/functions/__init__.py +21 -2
- pixeltable/functions/anthropic.py +16 -12
- pixeltable/functions/fireworks.py +63 -5
- pixeltable/functions/gemini.py +13 -3
- pixeltable/functions/globals.py +18 -6
- pixeltable/functions/huggingface.py +20 -38
- pixeltable/functions/image.py +7 -3
- pixeltable/functions/json.py +1 -0
- pixeltable/functions/llama_cpp.py +1 -4
- pixeltable/functions/mistralai.py +31 -20
- pixeltable/functions/ollama.py +4 -18
- pixeltable/functions/openai.py +201 -108
- pixeltable/functions/replicate.py +11 -10
- pixeltable/functions/string.py +70 -7
- pixeltable/functions/timestamp.py +21 -8
- pixeltable/functions/together.py +66 -52
- pixeltable/functions/video.py +1 -0
- pixeltable/functions/vision.py +14 -11
- pixeltable/functions/whisper.py +2 -1
- pixeltable/globals.py +60 -26
- pixeltable/index/__init__.py +1 -1
- pixeltable/index/btree.py +5 -3
- pixeltable/index/embedding_index.py +15 -14
- pixeltable/io/__init__.py +1 -1
- pixeltable/io/external_store.py +30 -25
- pixeltable/io/fiftyone.py +6 -14
- pixeltable/io/globals.py +33 -27
- pixeltable/io/hf_datasets.py +2 -1
- pixeltable/io/label_studio.py +77 -68
- pixeltable/io/pandas.py +33 -9
- pixeltable/io/parquet.py +9 -12
- pixeltable/iterators/__init__.py +1 -0
- pixeltable/iterators/audio.py +205 -0
- pixeltable/iterators/document.py +19 -8
- pixeltable/iterators/image.py +6 -24
- pixeltable/iterators/string.py +3 -6
- pixeltable/iterators/video.py +1 -7
- pixeltable/metadata/__init__.py +7 -1
- pixeltable/metadata/converters/convert_10.py +2 -2
- pixeltable/metadata/converters/convert_15.py +1 -5
- pixeltable/metadata/converters/convert_16.py +2 -4
- pixeltable/metadata/converters/convert_17.py +2 -4
- pixeltable/metadata/converters/convert_18.py +2 -4
- pixeltable/metadata/converters/convert_19.py +2 -5
- pixeltable/metadata/converters/convert_20.py +1 -4
- pixeltable/metadata/converters/convert_21.py +4 -6
- pixeltable/metadata/converters/convert_22.py +1 -0
- pixeltable/metadata/converters/convert_23.py +5 -5
- pixeltable/metadata/converters/convert_24.py +12 -13
- pixeltable/metadata/converters/convert_26.py +23 -0
- pixeltable/metadata/converters/util.py +3 -4
- pixeltable/metadata/notes.py +1 -0
- pixeltable/metadata/schema.py +13 -2
- pixeltable/plan.py +173 -98
- pixeltable/store.py +42 -26
- pixeltable/type_system.py +62 -54
- pixeltable/utils/arrow.py +1 -2
- pixeltable/utils/coco.py +16 -17
- pixeltable/utils/code.py +1 -1
- pixeltable/utils/console_output.py +6 -3
- pixeltable/utils/description_helper.py +7 -7
- pixeltable/utils/documents.py +3 -1
- pixeltable/utils/filecache.py +12 -7
- pixeltable/utils/http_server.py +9 -8
- pixeltable/utils/media_store.py +2 -1
- pixeltable/utils/pytorch.py +11 -14
- pixeltable/utils/s3.py +1 -0
- pixeltable/utils/sql.py +1 -0
- pixeltable/utils/transactional_directory.py +2 -2
- {pixeltable-0.3.2.dist-info → pixeltable-0.3.3.dist-info}/METADATA +6 -8
- pixeltable-0.3.3.dist-info/RECORD +163 -0
- pixeltable-0.3.2.dist-info/RECORD +0 -161
- {pixeltable-0.3.2.dist-info → pixeltable-0.3.3.dist-info}/LICENSE +0 -0
- {pixeltable-0.3.2.dist-info → pixeltable-0.3.3.dist-info}/WHEEL +0 -0
- {pixeltable-0.3.2.dist-info → pixeltable-0.3.3.dist-info}/entry_points.txt +0 -0
pixeltable/exprs/__init__.py
CHANGED
|
@@ -9,6 +9,7 @@ from .expr import Expr
|
|
|
9
9
|
from .expr_dict import ExprDict
|
|
10
10
|
from .expr_set import ExprSet
|
|
11
11
|
from .function_call import FunctionCall
|
|
12
|
+
from .globals import ArithmeticOperator, ComparisonOperator, LogicalOperator
|
|
12
13
|
from .in_predicate import InPredicate
|
|
13
14
|
from .inline_expr import InlineArray, InlineDict, InlineList
|
|
14
15
|
from .is_null import IsNull
|
|
@@ -17,10 +18,9 @@ from .json_path import RELATIVE_PATH_ROOT, JsonPath
|
|
|
17
18
|
from .literal import Literal
|
|
18
19
|
from .method_ref import MethodRef
|
|
19
20
|
from .object_ref import ObjectRef
|
|
20
|
-
from .row_builder import
|
|
21
|
+
from .row_builder import ColumnSlotIdx, ExecProfile, RowBuilder
|
|
21
22
|
from .rowid_ref import RowidRef
|
|
22
23
|
from .similarity_expr import SimilarityExpr
|
|
23
24
|
from .sql_element_cache import SqlElementCache
|
|
24
25
|
from .type_cast import TypeCast
|
|
25
26
|
from .variable import Variable
|
|
26
|
-
from .globals import ComparisonOperator, LogicalOperator, ArithmeticOperator
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import Any, Optional
|
|
3
|
+
from typing import Any, Optional, Union
|
|
4
4
|
|
|
5
5
|
import sqlalchemy as sql
|
|
6
6
|
|
|
7
7
|
import pixeltable.exceptions as excs
|
|
8
|
+
import pixeltable.exprs as exprs
|
|
8
9
|
import pixeltable.type_system as ts
|
|
9
10
|
|
|
10
11
|
from .data_row import DataRow
|
|
11
12
|
from .expr import Expr
|
|
12
13
|
from .globals import ArithmeticOperator
|
|
14
|
+
from .literal import Literal
|
|
13
15
|
from .row_builder import RowBuilder
|
|
14
16
|
from .sql_element_cache import SqlElementCache
|
|
15
17
|
|
|
@@ -18,6 +20,7 @@ class ArithmeticExpr(Expr):
|
|
|
18
20
|
"""
|
|
19
21
|
Allows arithmetic exprs on json paths
|
|
20
22
|
"""
|
|
23
|
+
|
|
21
24
|
def __init__(self, operator: ArithmeticOperator, op1: Expr, op2: Expr):
|
|
22
25
|
if op1.col_type.is_json_type() or op2.col_type.is_json_type() or operator == ArithmeticOperator.DIV:
|
|
23
26
|
# we assume it's a float
|
|
@@ -35,6 +38,14 @@ class ArithmeticExpr(Expr):
|
|
|
35
38
|
|
|
36
39
|
self.id = self._create_id()
|
|
37
40
|
|
|
41
|
+
@property
|
|
42
|
+
def _op1(self) -> Expr:
|
|
43
|
+
return self.components[0]
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def _op2(self) -> Expr:
|
|
47
|
+
return self.components[1]
|
|
48
|
+
|
|
38
49
|
def __repr__(self) -> str:
|
|
39
50
|
# add parentheses around operands that are ArithmeticExprs to express precedence
|
|
40
51
|
op1_str = f'({self._op1})' if isinstance(self._op1, ArithmeticExpr) else str(self._op1)
|
|
@@ -47,14 +58,6 @@ class ArithmeticExpr(Expr):
|
|
|
47
58
|
def _id_attrs(self) -> list[tuple[str, Any]]:
|
|
48
59
|
return super()._id_attrs() + [('operator', self.operator.value)]
|
|
49
60
|
|
|
50
|
-
@property
|
|
51
|
-
def _op1(self) -> Expr:
|
|
52
|
-
return self.components[0]
|
|
53
|
-
|
|
54
|
-
@property
|
|
55
|
-
def _op2(self) -> Expr:
|
|
56
|
-
return self.components[1]
|
|
57
|
-
|
|
58
61
|
def sql_expr(self, sql_elements: SqlElementCache) -> Optional[sql.ColumnElement]:
|
|
59
62
|
assert self.col_type.is_int_type() or self.col_type.is_float_type() or self.col_type.is_json_type()
|
|
60
63
|
left = sql_elements.get(self._op1)
|
|
@@ -73,7 +76,7 @@ class ArithmeticExpr(Expr):
|
|
|
73
76
|
# TODO: Should we cast the NULLs to NaNs when they are retrieved back into Python?
|
|
74
77
|
nullif = sql.sql.func.nullif(right, 0)
|
|
75
78
|
# We have to cast to a `float`, or else we'll get a `Decimal`
|
|
76
|
-
return sql.sql.expression.cast(left / nullif,
|
|
79
|
+
return sql.sql.expression.cast(left / nullif, self.col_type.to_sa_type())
|
|
77
80
|
if self.operator == ArithmeticOperator.MOD:
|
|
78
81
|
if self.col_type.is_int_type():
|
|
79
82
|
nullif = sql.sql.func.nullif(right, 0)
|
|
@@ -89,9 +92,9 @@ class ArithmeticExpr(Expr):
|
|
|
89
92
|
# mimic the behavior of Python's // operator.
|
|
90
93
|
nullif = sql.sql.func.nullif(right, 0)
|
|
91
94
|
if self.col_type.is_int_type():
|
|
92
|
-
return sql.sql.expression.cast(sql.func.floor(left / nullif),
|
|
95
|
+
return sql.sql.expression.cast(sql.func.floor(left / nullif), self.col_type.to_sa_type())
|
|
93
96
|
if self.col_type.is_float_type():
|
|
94
|
-
return sql.sql.expression.cast(sql.func.floor(left / nullif),
|
|
97
|
+
return sql.sql.expression.cast(sql.func.floor(left / nullif), self.col_type.to_sa_type())
|
|
95
98
|
assert False
|
|
96
99
|
|
|
97
100
|
def eval(self, data_row: DataRow, row_builder: RowBuilder) -> None:
|
|
@@ -99,30 +102,58 @@ class ArithmeticExpr(Expr):
|
|
|
99
102
|
op2_val = data_row[self._op2.slot_idx]
|
|
100
103
|
|
|
101
104
|
# if one or both columns is JsonTyped, we need a dynamic check that they are numeric
|
|
102
|
-
if self._op1.col_type.is_json_type() and not
|
|
105
|
+
if self._op1.col_type.is_json_type() and op1_val is not None and not isinstance(op1_val, (int, float)):
|
|
103
106
|
raise excs.Error(
|
|
104
|
-
f'{self.operator} requires numeric
|
|
105
|
-
|
|
107
|
+
f'{self.operator} requires numeric types, but {self._op1} has type {type(op1_val).__name__}'
|
|
108
|
+
)
|
|
109
|
+
if self._op2.col_type.is_json_type() and op2_val is not None and not isinstance(op2_val, (int, float)):
|
|
106
110
|
raise excs.Error(
|
|
107
|
-
f'{self.operator} requires numeric
|
|
108
|
-
|
|
109
|
-
|
|
111
|
+
f'{self.operator} requires numeric types, but {self._op2} has type {type(op2_val).__name__}'
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
data_row[self.slot_idx] = self.eval_nullable(op1_val, op2_val)
|
|
115
|
+
|
|
116
|
+
def eval_nullable(
|
|
117
|
+
self, op1_val: Union[int, float, None], op2_val: Union[int, float, None]
|
|
118
|
+
) -> Union[int, float, None]:
|
|
119
|
+
"""
|
|
120
|
+
Return the result of evaluating the expression on two nullable int/float operands,
|
|
121
|
+
None is interpreted as SQL NULL
|
|
122
|
+
"""
|
|
110
123
|
if op1_val is None or op2_val is None:
|
|
111
|
-
|
|
112
|
-
|
|
124
|
+
return None
|
|
125
|
+
return self.eval_non_null(op1_val, op2_val)
|
|
113
126
|
|
|
127
|
+
def eval_non_null(self, op1_val: Union[int, float], op2_val: Union[int, float]) -> Union[int, float]:
|
|
128
|
+
"""
|
|
129
|
+
Return the result of evaluating the expression on two int/float operands
|
|
130
|
+
"""
|
|
114
131
|
if self.operator == ArithmeticOperator.ADD:
|
|
115
|
-
|
|
132
|
+
return op1_val + op2_val
|
|
116
133
|
elif self.operator == ArithmeticOperator.SUB:
|
|
117
|
-
|
|
134
|
+
return op1_val - op2_val
|
|
118
135
|
elif self.operator == ArithmeticOperator.MUL:
|
|
119
|
-
|
|
136
|
+
return op1_val * op2_val
|
|
120
137
|
elif self.operator == ArithmeticOperator.DIV:
|
|
121
|
-
|
|
138
|
+
return op1_val / op2_val
|
|
122
139
|
elif self.operator == ArithmeticOperator.MOD:
|
|
123
|
-
|
|
140
|
+
return op1_val % op2_val
|
|
124
141
|
elif self.operator == ArithmeticOperator.FLOORDIV:
|
|
125
|
-
|
|
142
|
+
return op1_val // op2_val
|
|
143
|
+
|
|
144
|
+
def as_literal(self) -> Optional[Literal]:
|
|
145
|
+
op1_lit = self._op1.as_literal()
|
|
146
|
+
if op1_lit is None:
|
|
147
|
+
return None
|
|
148
|
+
op2_lit = self._op2.as_literal()
|
|
149
|
+
if op2_lit is None:
|
|
150
|
+
return None
|
|
151
|
+
op1_val = op1_lit.val
|
|
152
|
+
assert op1_lit.col_type.is_numeric_type() or op1_val is None
|
|
153
|
+
op2_val = op2_lit.val
|
|
154
|
+
assert op2_lit.col_type.is_numeric_type() or op2_val is None
|
|
155
|
+
|
|
156
|
+
return Literal(self.eval_nullable(op1_val, op2_val), self.col_type) # type: ignore[arg-type]
|
|
126
157
|
|
|
127
158
|
def _as_dict(self) -> dict:
|
|
128
159
|
return {'operator': self.operator.value, **super()._as_dict()}
|
pixeltable/exprs/array_slice.py
CHANGED
|
@@ -15,6 +15,7 @@ class ArraySlice(Expr):
|
|
|
15
15
|
"""
|
|
16
16
|
Slice operation on an array, eg, t.array_col[:, 1:2].
|
|
17
17
|
"""
|
|
18
|
+
|
|
18
19
|
def __init__(self, arr: Expr, index: tuple[Union[int, slice], ...]):
|
|
19
20
|
assert arr.col_type.is_array_type()
|
|
20
21
|
# determine result type
|
|
@@ -68,4 +69,3 @@ class ArraySlice(Expr):
|
|
|
68
69
|
else:
|
|
69
70
|
index.append(el)
|
|
70
71
|
return cls(components[0], tuple(index))
|
|
71
|
-
|
|
@@ -7,6 +7,7 @@ import sqlalchemy as sql
|
|
|
7
7
|
|
|
8
8
|
import pixeltable.type_system as ts
|
|
9
9
|
from pixeltable import catalog
|
|
10
|
+
|
|
10
11
|
from .column_ref import ColumnRef
|
|
11
12
|
from .data_row import DataRow
|
|
12
13
|
from .expr import Expr
|
|
@@ -19,6 +20,7 @@ class ColumnPropertyRef(Expr):
|
|
|
19
20
|
|
|
20
21
|
The properties themselves are type-specific and may or may not need to reference the underlying column data.
|
|
21
22
|
"""
|
|
23
|
+
|
|
22
24
|
class Property(enum.Enum):
|
|
23
25
|
ERRORTYPE = 0
|
|
24
26
|
ERRORMSG = 1
|
|
@@ -103,4 +105,3 @@ class ColumnPropertyRef(Expr):
|
|
|
103
105
|
assert 'prop' in d
|
|
104
106
|
assert isinstance(components[0], ColumnRef)
|
|
105
107
|
return cls(components[0], cls.Property(d['prop']))
|
|
106
|
-
|
pixeltable/exprs/column_ref.py
CHANGED
|
@@ -51,8 +51,9 @@ class ColumnRef(Expr):
|
|
|
51
51
|
super().__init__(col.col_type)
|
|
52
52
|
assert col.tbl is not None
|
|
53
53
|
self.col = col
|
|
54
|
-
self.is_unstored_iter_col =
|
|
54
|
+
self.is_unstored_iter_col = (
|
|
55
55
|
col.tbl.is_component_view() and col.tbl.is_iterator_column(col) and not col.is_stored
|
|
56
|
+
)
|
|
56
57
|
self.iter_arg_ctx = None
|
|
57
58
|
# number of rowid columns in the base table
|
|
58
59
|
self.base_rowid_len = col.tbl.base.num_rowid_columns() if self.is_unstored_iter_col else 0
|
|
@@ -83,10 +84,11 @@ class ColumnRef(Expr):
|
|
|
83
84
|
assert len(self.iter_arg_ctx.target_slot_idxs) == 1 # a single inline dict
|
|
84
85
|
|
|
85
86
|
def _id_attrs(self) -> list[tuple[str, Any]]:
|
|
86
|
-
return (
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
return super()._id_attrs() + [
|
|
88
|
+
('tbl_id', self.col.tbl.id),
|
|
89
|
+
('col_id', self.col.id),
|
|
90
|
+
('perform_validation', self.perform_validation),
|
|
91
|
+
]
|
|
90
92
|
|
|
91
93
|
# override
|
|
92
94
|
def _retarget(self, tbl_versions: dict[UUID, catalog.TableVersion]) -> ColumnRef:
|
|
@@ -99,14 +101,18 @@ class ColumnRef(Expr):
|
|
|
99
101
|
from .column_property_ref import ColumnPropertyRef
|
|
100
102
|
|
|
101
103
|
# resolve column properties
|
|
102
|
-
if
|
|
103
|
-
|
|
104
|
+
if (
|
|
105
|
+
name == ColumnPropertyRef.Property.ERRORTYPE.name.lower()
|
|
106
|
+
or name == ColumnPropertyRef.Property.ERRORMSG.name.lower()
|
|
107
|
+
):
|
|
104
108
|
property_is_present = self.col.is_stored and (self.col.is_computed or self.col_type.is_media_type())
|
|
105
109
|
if not property_is_present:
|
|
106
110
|
raise excs.Error(f'{name} only valid for a stored computed or media column: {self}')
|
|
107
111
|
return ColumnPropertyRef(self, ColumnPropertyRef.Property[name.upper()])
|
|
108
|
-
if
|
|
109
|
-
|
|
112
|
+
if (
|
|
113
|
+
name == ColumnPropertyRef.Property.FILEURL.name.lower()
|
|
114
|
+
or name == ColumnPropertyRef.Property.LOCALPATH.name.lower()
|
|
115
|
+
):
|
|
110
116
|
if not self.col.col_type.is_media_type():
|
|
111
117
|
raise excs.Error(f'{name} only valid for image/video/audio/document columns: {self}')
|
|
112
118
|
if self.col.is_computed and not self.col.is_stored:
|
|
@@ -115,12 +121,14 @@ class ColumnRef(Expr):
|
|
|
115
121
|
|
|
116
122
|
if self.col_type.is_json_type():
|
|
117
123
|
from .json_path import JsonPath
|
|
124
|
+
|
|
118
125
|
return JsonPath(self, [name])
|
|
119
126
|
|
|
120
127
|
return super().__getattr__(name)
|
|
121
128
|
|
|
122
129
|
def similarity(self, item: Any, *, idx: Optional[str] = None) -> Expr:
|
|
123
130
|
from .similarity_expr import SimilarityExpr
|
|
131
|
+
|
|
124
132
|
return SimilarityExpr(self, item, idx_name=idx)
|
|
125
133
|
|
|
126
134
|
def default_column_name(self) -> Optional[str]:
|
|
@@ -206,11 +214,11 @@ class ColumnRef(Expr):
|
|
|
206
214
|
return
|
|
207
215
|
|
|
208
216
|
# if this is a new base row, we need to instantiate a new iterator
|
|
209
|
-
if self.base_rowid != data_row.pk[:self.base_rowid_len]:
|
|
217
|
+
if self.base_rowid != data_row.pk[: self.base_rowid_len]:
|
|
210
218
|
row_builder.eval(data_row, self.iter_arg_ctx)
|
|
211
219
|
iterator_args = data_row[self.iter_arg_ctx.target_slot_idxs[0]]
|
|
212
220
|
self.iterator = self.col.tbl.iterator_cls(**iterator_args)
|
|
213
|
-
self.base_rowid = data_row.pk[:self.base_rowid_len]
|
|
221
|
+
self.base_rowid = data_row.pk[: self.base_rowid_len]
|
|
214
222
|
self.iterator.set_pos(data_row.pk[self.pos_idx])
|
|
215
223
|
res = next(self.iterator)
|
|
216
224
|
data_row[self.slot_idx] = res[self.col.name]
|
|
@@ -224,7 +232,7 @@ class ColumnRef(Expr):
|
|
|
224
232
|
'tbl_id': str(tbl.id),
|
|
225
233
|
'tbl_version': version,
|
|
226
234
|
'col_id': self.col.id,
|
|
227
|
-
'perform_validation': self.perform_validation
|
|
235
|
+
'perform_validation': self.perform_validation,
|
|
228
236
|
}
|
|
229
237
|
|
|
230
238
|
@classmethod
|
|
@@ -240,6 +248,3 @@ class ColumnRef(Expr):
|
|
|
240
248
|
col = cls.get_column(d)
|
|
241
249
|
perform_validation = d['perform_validation']
|
|
242
250
|
return cls(col, perform_validation=perform_validation)
|
|
243
|
-
|
|
244
|
-
def is_constant(self) -> bool:
|
|
245
|
-
return False
|
pixeltable/exprs/comparison.py
CHANGED
|
@@ -39,8 +39,12 @@ class Comparison(Expr):
|
|
|
39
39
|
self.components = [op1, op2]
|
|
40
40
|
|
|
41
41
|
import pixeltable.index as index
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
|
|
43
|
+
if (
|
|
44
|
+
self.is_search_arg_comparison
|
|
45
|
+
and self._op2.col_type.is_string_type()
|
|
46
|
+
and len(self._op2.val) >= index.BtreeIndex.MAX_STRING_LEN
|
|
47
|
+
):
|
|
44
48
|
# we can't use an index for this after all
|
|
45
49
|
raise excs.Error(
|
|
46
50
|
f'String literal too long for comparison against indexed column {self._op1.col.name!r} '
|
|
@@ -60,8 +60,7 @@ class CompoundPredicate(Expr):
|
|
|
60
60
|
def _id_attrs(self) -> list[tuple[str, Any]]:
|
|
61
61
|
return super()._id_attrs() + [('operator', self.operator.value)]
|
|
62
62
|
|
|
63
|
-
def split_conjuncts(
|
|
64
|
-
self, condition: Callable[[Expr], bool]) -> tuple[list[Expr], Optional[Expr]]:
|
|
63
|
+
def split_conjuncts(self, condition: Callable[[Expr], bool]) -> tuple[list[Expr], Optional[Expr]]:
|
|
65
64
|
if self.operator == LogicalOperator.OR or self.operator == LogicalOperator.NOT:
|
|
66
65
|
return super().split_conjuncts(condition)
|
|
67
66
|
matches = [op for op in self.components if condition(op)]
|
|
@@ -97,4 +96,3 @@ class CompoundPredicate(Expr):
|
|
|
97
96
|
def _from_dict(cls, d: dict, components: list[Expr]) -> CompoundPredicate:
|
|
98
97
|
assert 'operator' in d
|
|
99
98
|
return cls(LogicalOperator(d['operator']), components)
|
|
100
|
-
|
pixeltable/exprs/data_row.py
CHANGED
|
@@ -6,10 +6,10 @@ import urllib.parse
|
|
|
6
6
|
import urllib.request
|
|
7
7
|
from typing import Any, Optional
|
|
8
8
|
|
|
9
|
-
import PIL
|
|
10
|
-
import PIL.Image
|
|
11
9
|
import numpy as np
|
|
12
10
|
import pgvector.sqlalchemy # type: ignore[import-untyped]
|
|
11
|
+
import PIL
|
|
12
|
+
import PIL.Image
|
|
13
13
|
import sqlalchemy as sql
|
|
14
14
|
|
|
15
15
|
from pixeltable import env
|