Skip to content

Commit ec45936

Browse files
committed
Merge branch '28-set-params-with-aliases' into 'dev'
Resolve "Bubble up `set_parameter` with aliases" #28 Closes #28 See merge request objectbox/objectbox-python!18
2 parents 083cbba + 7d0bdb5 commit ec45936

6 files changed

Lines changed: 114 additions & 2 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,5 @@ share/python-wheels/
3333
.installed.cfg
3434
*.egg
3535
MANIFEST
36-
**/__pycache__
36+
**/__pycache__
37+
env/

objectbox/c.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,13 @@ def c_array_pointer(py_list: Union[List[Any], np.ndarray], c_type):
696696
ctypes.c_size_t])
697697

698698
# OBX_C_API obx_err obx_query_param_alias_vector_float32(OBX_query* query, const char* alias, const float* value, size_t element_count);
699-
# TODO
699+
obx_query_param_alias_vector_float32 = c_fn_rc('obx_query_param_alias_vector_float32', [OBX_query_p, ctypes.c_char_p, ctypes.POINTER(ctypes.c_float), ctypes.c_size_t])
700+
701+
# OBX_C_API obx_err obx_query_param_alias_string(OBX_query* query, const char* alias, const char* value);
702+
obx_query_param_alias_string = c_fn_rc('obx_query_param_alias_string', [OBX_query_p, ctypes.c_char_p, ctypes.c_char_p])
703+
704+
# OBX_C_API obx_err obx_query_param_alias_int(OBX_query* query, const char* alias, int64_t value);
705+
obx_query_param_alias_int = c_fn_rc('obx_query_param_alias_int', [OBX_query_p, ctypes.c_char_p, ctypes.c_int64])
700706

701707
# OBX_C_API obx_err obx_qb_order(OBX_query_builder* builder, obx_schema_id property_id, OBXOrderFlags flags);
702708
obx_qb_order = c_fn_rc('obx_qb_order', [OBX_query_builder_p, obx_schema_id, OBXOrderFlags])

objectbox/condition.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ def __init__(self, property_id: int, op: _QueryConditionOp, args: Dict[str, Any]
2525
self._property_id = property_id
2626
self._op = op
2727
self._args = args
28+
self._alias = None
29+
30+
def alias(self, value: str):
31+
self._alias = value
32+
return self
2833

2934
def _get_op_map(self):
3035
return {
@@ -52,6 +57,9 @@ def _apply_eq(self, qb: 'QueryBuilder'):
5257
else:
5358
raise Exception(f"Unsupported type for 'EQ': {type(value)}")
5459

60+
if self._alias is not None:
61+
qb.alias(self._alias)
62+
5563
def _apply_not_eq(self, qb: 'QueryBuilder'):
5664
value = self._args['value']
5765
case_sensitive = self._args['case_sensitive']
@@ -62,6 +70,9 @@ def _apply_not_eq(self, qb: 'QueryBuilder'):
6270
else:
6371
raise Exception(f"Unsupported type for 'NOT_EQ': {type(value)}")
6472

73+
if self._alias is not None:
74+
qb.alias(self._alias)
75+
6576
def _apply_contains(self, qb: 'QueryBuilder'):
6677
value = self._args['value']
6778
case_sensitive = self._args['case_sensitive']
@@ -70,6 +81,9 @@ def _apply_contains(self, qb: 'QueryBuilder'):
7081
else:
7182
raise Exception(f"Unsupported type for 'CONTAINS': {type(value)}")
7283

84+
if self._alias is not None:
85+
qb.alias(self._alias)
86+
7387
def _apply_starts_with(self, qb: 'QueryBuilder'):
7488
value = self._args['value']
7589
case_sensitive = self._args['case_sensitive']
@@ -78,6 +92,9 @@ def _apply_starts_with(self, qb: 'QueryBuilder'):
7892
else:
7993
raise Exception(f"Unsupported type for 'STARTS_WITH': {type(value)}")
8094

95+
if self._alias is not None:
96+
qb.alias(self._alias)
97+
8198
def _apply_ends_with(self, qb: 'QueryBuilder'):
8299
value = self._args['value']
83100
case_sensitive = self._args['case_sensitive']
@@ -86,6 +103,9 @@ def _apply_ends_with(self, qb: 'QueryBuilder'):
86103
else:
87104
raise Exception(f"Unsupported type for 'ENDS_WITH': {type(value)}")
88105

106+
if self._alias is not None:
107+
qb.alias(self._alias)
108+
89109
def _apply_gt(self, qb: 'QueryBuilder'):
90110
value = self._args['value']
91111
case_sensitive = self._args['case_sensitive']
@@ -96,6 +116,9 @@ def _apply_gt(self, qb: 'QueryBuilder'):
96116
else:
97117
raise Exception(f"Unsupported type for 'GT': {type(value)}")
98118

119+
if self._alias is not None:
120+
qb.alias(self._alias)
121+
99122
def _apply_gte(self, qb: 'QueryBuilder'):
100123
value = self._args['value']
101124
case_sensitive = self._args['case_sensitive']
@@ -106,6 +129,9 @@ def _apply_gte(self, qb: 'QueryBuilder'):
106129
else:
107130
raise Exception(f"Unsupported type for 'GTE': {type(value)}")
108131

132+
if self._alias is not None:
133+
qb.alias(self._alias)
134+
109135
def _apply_lt(self, qb: 'QueryCondition'):
110136
value = self._args['value']
111137
case_sensitive = self._args['case_sensitive']
@@ -116,6 +142,9 @@ def _apply_lt(self, qb: 'QueryCondition'):
116142
else:
117143
raise Exception("Unsupported type for 'LT': " + str(type(value)))
118144

145+
if self._alias is not None:
146+
qb.alias(self._alias)
147+
119148
def _apply_lte(self, qb: 'QueryBuilder'):
120149
value = self._args['value']
121150
case_sensitive = self._args['case_sensitive']
@@ -126,6 +155,9 @@ def _apply_lte(self, qb: 'QueryBuilder'):
126155
else:
127156
raise Exception(f"Unsupported type for 'LTE': {type(value)}")
128157

158+
if self._alias is not None:
159+
qb.alias(self._alias)
160+
129161
def _apply_between(self, qb: 'QueryBuilder'):
130162
a = self._args['a']
131163
b = self._args['b']
@@ -134,6 +166,9 @@ def _apply_between(self, qb: 'QueryBuilder'):
134166
else:
135167
raise Exception(f"Unsupported type for 'BETWEEN': {type(a)}")
136168

169+
if self._alias is not None:
170+
qb.alias(self._alias)
171+
137172
def _apply_nearest_neighbor(self, qb: 'QueryBuilder'):
138173
query_vector = self._args['query_vector']
139174
element_count = self._args['element_count']
@@ -149,5 +184,8 @@ def _apply_nearest_neighbor(self, qb: 'QueryBuilder'):
149184
else:
150185
raise Exception(f"Unsupported type for 'NEAREST_NEIGHBOR': {type(query_vector)}")
151186

187+
if self._alias is not None:
188+
qb.alias(self._alias)
189+
152190
def apply(self, qb: 'QueryBuilder'):
153191
self._get_op_map()[self._op](qb)

objectbox/query.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,18 @@ def set_parameter_vector_f32(self,
123123
num_el = len(value)
124124
obx_query_param_vector_float32(self._c_query, self._entity.id, prop_id, c_value, num_el)
125125
return self
126+
127+
def offset(self, offset: int):
128+
return obx_query_offset(self._c_query, offset)
129+
130+
def limit(self, limit: int):
131+
return obx_query_limit(self._c_query, limit)
132+
133+
def set_parameter_alias_string(self, alias: str, value: str):
134+
return obx_query_param_alias_string(self._c_query,c_str(alias), c_str(value))
135+
136+
def set_parameter_alias_int(self, alias: str, value: int):
137+
return obx_query_param_alias_int(self._c_query, c_str(alias), value)
138+
139+
def set_parameter_alias_vector_f32(self, alias: str, value: Union[List[float], np.ndarray]):
140+
return obx_query_param_alias_vector_float32(self._c_query, c_str(alias), c_array(value, ctypes.c_float), len(value))

objectbox/query_builder.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,7 @@ def all(self, conditions: List[obx_qb_cond]) -> obx_qb_cond:
130130
def build(self) -> Query:
131131
c_query = obx_query(self._c_builder)
132132
return Query(c_query, self._box)
133+
134+
def alias(self, alias: str):
135+
obx_qb_param_alias(self._c_builder, c_str(alias))
136+
return self

tests/test_query.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,3 +249,51 @@ def test_set_parameter():
249249

250250
query.set_parameter_int("vector", 2)
251251
assert query.find_ids() == sorted([2, 3])
252+
253+
254+
def test_set_parameter_alias():
255+
db = create_test_objectbox()
256+
box = objectbox.Box(db, TestEntity)
257+
258+
box.put(TestEntity(str="Foo", int64=2, int32=703, int8=101))
259+
box.put(TestEntity(str="FooBar", int64=10, int32=49, int8=45))
260+
261+
box_vector = objectbox.Box(db, VectorEntity)
262+
box_vector.put(VectorEntity(name="Object 1", vector=[1, 1]))
263+
box_vector.put(VectorEntity(name="Object 2", vector=[2, 2]))
264+
box_vector.put(VectorEntity(name="Object 3", vector=[3, 3]))
265+
box_vector.put(VectorEntity(name="Object 4", vector=[4, 4]))
266+
box_vector.put(VectorEntity(name="Object 5", vector=[5, 5]))
267+
268+
str_prop: Property = TestEntity.properties[1]
269+
qb = box.query(str_prop.equals("Foo").alias("foo_filter"))
270+
271+
query = qb.build()
272+
assert query.find()[0].str == "Foo"
273+
assert query.count() == 1
274+
275+
query.set_parameter_alias_string("foo_filter", "FooBar")
276+
277+
assert query.find()[0].str == "FooBar"
278+
assert query.count() == 1
279+
280+
int_prop: Property = TestEntity.properties[3]
281+
qb = box.query(int_prop.greater_than(5).alias("greater_than_filter"))
282+
283+
query = qb.build()
284+
assert query.count() == 1
285+
assert query.find()[0].str == "FooBar"
286+
287+
query.set_parameter_alias_int("greater_than_filter", 1)
288+
289+
assert query.count() == 2
290+
291+
vector_prop: Property = VectorEntity.get_property("vector")
292+
293+
query = box_vector.query(vector_prop.nearest_neighbor([3.4, 3.4], 3).alias("nearest_neighbour_filter")).build()
294+
assert query.count() == 3
295+
assert query.find_ids() == sorted([3, 4, 2])
296+
297+
query.set_parameter_alias_vector_f32("nearest_neighbour_filter", [4.9, 4.9])
298+
assert query.count() == 3
299+
assert query.find_ids() == sorted([5, 4, 3])

0 commit comments

Comments
 (0)