|
@@ -183,6 +183,7 @@ class LeFilteredQuery(LeQuery):
|
183
|
183
|
err_l["filter %d" % i] = e
|
184
|
184
|
|
185
|
185
|
for field, operator, value in filters:
|
|
186
|
+ err_key = "%s %s %s" % (field, operator, value) #to push in err_l
|
186
|
187
|
# Spliting field name to be able to detect a relational field
|
187
|
188
|
field_spl = field.split('.')
|
188
|
189
|
if len(field_spl) == 2:
|
|
@@ -198,19 +199,33 @@ field name" % fieldname)
|
198
|
199
|
if isinstance(ret, Exception):
|
199
|
200
|
err_l[field] = ret
|
200
|
201
|
continue
|
201
|
|
- # Check that the field is relational if ref_field given
|
202
|
|
- if ref_field is not None and not cls.field(field).is_reference():
|
|
202
|
+ field_datahandler = self._target_class.field(field)
|
|
203
|
+ if ref_field is not None and not field_datahandler.is_reference():
|
203
|
204
|
# inconsistency
|
204
|
|
- err_l[field] = NameError( "The field '%s' in %s is not\
|
|
205
|
+ err_l[field] = NameError( "The field '%s' in %s is not \
|
205
|
206
|
a relational field, but %s.%s was present in the filter"
|
206
|
207
|
% ( field,
|
|
208
|
+ self._target_class.__name__,
|
207
|
209
|
field,
|
208
|
210
|
ref_field))
|
209
|
|
- # Prepare relational field
|
210
|
|
- if self._target_class.field(field).is_reference():
|
|
211
|
+ if field_datahandler.is_reference():
|
|
212
|
+ #Relationnal field
|
|
213
|
+ if ref_field is None:
|
|
214
|
+ # ref_field default value
|
|
215
|
+ ref_uid = set([ lc._uid for lc in field_datahandler.linked_classes])
|
|
216
|
+ if len(ref_uid) == 1:
|
|
217
|
+ ref_field = ref_uid[0]
|
|
218
|
+ else:
|
|
219
|
+ if len(ref_uid) > 1:
|
|
220
|
+ err_l[err_key] = RuntimeError("The referenced classes are identified by fields with different name. Unable to determine wich field to use for the reference")
|
|
221
|
+ else:
|
|
222
|
+ err_l[err_key] = RuntimeError("Unknow error when trying to determine wich field to use for the relational filter")
|
|
223
|
+ continue
|
|
224
|
+ # Prepare relational field
|
211
|
225
|
ret = self._prepare_relational_fields(field, ref_field)
|
212
|
226
|
if isinstance(ret, Exception):
|
213
|
|
- err_l[field] = ret
|
|
227
|
+ err_l[err_key] = ret
|
|
228
|
+ continue
|
214
|
229
|
else:
|
215
|
230
|
rel_filters.append((ret, operator, value))
|
216
|
231
|
else:
|
|
@@ -221,6 +236,30 @@ a relational field, but %s.%s was present in the filter"
|
221
|
236
|
"Error while preparing filters : ",
|
222
|
237
|
err_l)
|
223
|
238
|
return (res_filters, rel_filters)
|
|
239
|
+
|
|
240
|
+ ## @brief Prepare & check relational field
|
|
241
|
+ #
|
|
242
|
+ # The result is a tuple with (field, ref_field, concerned_classes), with :
|
|
243
|
+ # - field the target_class field name
|
|
244
|
+ # - ref_field the concerned_classes field names
|
|
245
|
+ # - concerned_classes a set of concerned LeObject classes
|
|
246
|
+ # @param field str : The target_class field name
|
|
247
|
+ # @param ref_field str : The referenced class field name
|
|
248
|
+ # @return a tuple(field, concerned_classes, ref_field) or an Exception class instance
|
|
249
|
+ def _prepare_relational_fields(self,field, ref_field):
|
|
250
|
+ field_dh = self._target_class.field(field)
|
|
251
|
+ concerned_classes = []
|
|
252
|
+ linked_classes = [] if field_dh.linked_classes is None else field_dh.linked_classes
|
|
253
|
+ for l_class in linked_classes:
|
|
254
|
+ try:
|
|
255
|
+ l_class.field(ref_field)
|
|
256
|
+ concerned_classes.append(l_class)
|
|
257
|
+ except KeyError:
|
|
258
|
+ pass
|
|
259
|
+ if len(concerned_classes) > 0:
|
|
260
|
+ return (field, ref_field, concerned_classes)
|
|
261
|
+ else:
|
|
262
|
+ return ValueError("None of the linked class of field %s has a field named '%s'" % (field, ref_field))
|
224
|
263
|
|
225
|
264
|
## @brief Check and split a query filter
|
226
|
265
|
# @note The query_filter format is "FIELD OPERATOR VALUE"
|
|
@@ -249,7 +288,7 @@ a relational field, but %s.%s was present in the filter"
|
249
|
288
|
for operator in cls._query_operators[1:]:
|
250
|
289
|
op_re_piece += '|(%s)'%operator.replace(' ', '\s')
|
251
|
290
|
op_re_piece += ')'
|
252
|
|
- cls._query_re = re.compile('^\s*(?P<field>(((superior)|(subordinate))\.)?[a-z_][a-z0-9\-_]*)\s*'+op_re_piece+'\s*(?P<value>.*)\s*$', flags=re.IGNORECASE)
|
|
291
|
+ cls._query_re = re.compile('^\s*(?P<field>([a-z_][a-z0-9\-_]*\.)?[a-z_][a-z0-9\-_]*)\s*'+op_re_piece+'\s*(?P<value>.*)\s*$', flags=re.IGNORECASE)
|
253
|
292
|
pass
|
254
|
293
|
|
255
|
294
|
@classmethod
|