Browse Source

More tests & debug on multi datasource queries + em_test update

- Added missing allowed_classes options to some references in em_test
Yann Weber 8 years ago
parent
commit
0f9b07f08a

+ 2
- 2
em_test.py View File

@@ -276,7 +276,7 @@ person.new_field(   'linked_texts',
276 276
                     data_handler = 'list',
277 277
                     back_reference = ('Text', 'linked_persons'),
278 278
                     group = editorial_person_group,
279
-)
279
+                    allowed_classes = [text])
280 280
 
281 281
 text.new_field( 'linked_persons',
282 282
                 display_name = {
@@ -286,7 +286,7 @@ text.new_field( 'linked_persons',
286 286
                 data_handler = 'list',
287 287
                 back_reference = ('Person', 'linked_texts'),
288 288
                 group = editorial_person_group,
289
-)
289
+                allowed_classes = [person])
290 290
 
291 291
 #####################
292 292
 # Index classes     # <--- Note :   using a different datasource for testing

BIN
examples/em_test.pickle View File


+ 24
- 7
lodel/leapi/query.py View File

@@ -1,6 +1,8 @@
1 1
 #-*- coding: utf-8 -*-
2 2
 
3 3
 import re
4
+import copy
5
+
4 6
 from .leobject import LeObject, LeApiErrors, LeApiDataCheckError
5 7
 from lodel.plugin.hooks import LodelHook
6 8
 from lodel import logger
@@ -157,6 +159,7 @@ class LeFilteredQuery(LeQuery):
157 159
     #
158 160
     #@param query_filter list|tuple|str : A single filter or a list of filters
159 161
     #@see LeFilteredQuery._prepare_filters()
162
+    #@warning Does not support multiple UID
160 163
     def set_query_filter(self, query_filter):
161 164
         if isinstance(query_filter, str):
162 165
             query_filter = [query_filter]
@@ -175,15 +178,21 @@ class LeFilteredQuery(LeQuery):
175 178
             tmp_rel_filter = dict() #designed to stores rel_field of same DS
176 179
             # First step : simplification
177 180
             # Trying to delete relational filters done on referenced class uid
178
-            for tclass, tfield in ref_dict.items():
181
+            for tclass, tfield in copy.copy(ref_dict).items():
179 182
                 #tclass : reference target class
180 183
                 #tfield : referenced field from target class
181
-                if tfield == tclass.uid_fieldname:
184
+                #
185
+                #   !!!WARNING!!!
186
+                # The line below brake multi UID support
187
+                #
188
+                if tfield == tclass.uid_fieldname()[0]:
182 189
                     #This relational filter can be simplified as 
183 190
                     # ref_field, op, value
184 191
                     # Note : we will have to dedup filters_orig
185 192
                     filters_orig.append((rfield, op, value))
186 193
                     del(ref_dict[tclass])
194
+            if len(ref_dict) == 0:
195
+                continue
187 196
             #Determine what to do with other relational filters given 
188 197
             # referenced class datasource
189 198
             #Remember : each class in a relational filter has the same 
@@ -268,6 +277,7 @@ class LeFilteredQuery(LeQuery):
268 277
     #@param filters_l list : This list of str or tuple (or both)
269 278
     #@return a tuple(FILTERS, RELATIONNAL_FILTERS
270 279
     #@todo move this doc in another place (a dedicated page ?)
280
+    #@warning Does not supports multiple UID for an EmClass
271 281
     def _prepare_filters(self, filters_l):
272 282
         filters = list()
273 283
         res_filters = list()
@@ -294,7 +304,7 @@ class LeFilteredQuery(LeQuery):
294 304
             else:
295 305
                 err_l[field] = NameError(   "'%s' is not a valid relational \
296 306
 field name" % fieldname)
297
-                continue   
307
+                continue
298 308
             # Checking field against target_class
299 309
             ret = self._check_field(self._target_class, field)
300 310
             if isinstance(ret, Exception):
@@ -313,9 +323,15 @@ a relational field, but %s.%s was present in the filter"
313 323
                 #Relationnal field
314 324
                 if ref_field is None:
315 325
                     # ref_field default value
316
-                    ref_uid = set(
317
-                        [lc._uid for lc in field_datahandler.linked_classes])
318
-                    if len(ref_uid) == 1:
326
+                    #
327
+                    #   !!! WARNING !!!
328
+                    # This piece of code does not supports multiple UID for an
329
+                    # emclass
330
+                    #
331
+                    ref_uid = [ 
332
+                        lc._uid[0] for lc in field_datahandler.linked_classes]
333
+
334
+                    if len(set(ref_uid)) == 1:
319 335
                         ref_field = ref_uid[0]
320 336
                     else:
321 337
                         if len(ref_uid) > 1:
@@ -442,7 +458,8 @@ field to use for the relational filter"
442 458
                 if r_ds is None:
443 459
                     r_ds = ref_class._datasource_name
444 460
                 elif ref_class._datasource_name != r_ds:
445
-                    return RuntimeError("All referenced class doesn't have the same datasource. Query not possible")
461
+                    return RuntimeError("All referenced class doesn't have the\
462
+ same datasource. Query not possible")
446 463
                 if ref_field in ref_class.fieldnames(True):
447 464
                     ref_dict[ref_class] = ref_field
448 465
                 else:

BIN
tests/editorial_model.pickle View File


+ 41
- 0
tests/leapi/query/test_filtered.py View File

@@ -130,3 +130,44 @@ class LeFilteredQueryMultiDataHandlerTestCase(unittest.TestCase):
130 130
             qinfos['query_filter'],
131 131
             ([('title', '=', 'super titre !')],[])) 
132 132
         self.assertEqual(qinfos['field_list'], ['title'])
133
+
134
+    def test_uid_as_ref_field(self):
135
+        """ Testing basic query optimisation with a relationnal filter 
136
+            with lodel_id as referenced field"""
137
+        getq = LeGetQuery(
138
+            dyncode.Indextheme,
139
+            "texts.lodel_id in 1,2,3,42")
140
+        qinfos = getq.dump_infos()
141
+        #No subqueries should be created because referenced field is 
142
+        #the referenced class UID
143
+        self.assertEqual(qinfos['subqueries'],[])
144
+        self.assertEqual(
145
+            qinfos['query_filter'], 
146
+            ([('texts', 'in', '1,2,3,42')], []))
147
+
148
+    def test_implicit_uid(self):
149
+        """ Testing query with an UID as implicit referenced field for a 
150
+            relationnal filter """
151
+        getq = LeGetQuery(
152
+            dyncode.Indextheme,
153
+            "texts in 13,1337,357,80")
154
+        qinfos = getq.dump_infos()
155
+        #No subqueries expected
156
+        self.assertEqual(qinfos['subqueries'],[])
157
+        self.assertEqual(
158
+            qinfos['query_filter'], 
159
+            ([('texts', 'in', '13,1337,357,80')], []))
160
+
161
+    def test_same_datasource(self):
162
+        """ Testing a query with relationnal filters concerning only one
163
+            datasource to check for 'false positive' in subqueries creation """ 
164
+        getq = LeGetQuery(
165
+            dyncode.Text,
166
+            "linked_persons.fullname = John Doe")
167
+        qinfos = getq.dump_infos()
168
+        self.assertEqual(qinfos['subqueries'],[])
169
+        self.assertEqual(
170
+            qinfos['query_filter'], 
171
+            (   [],
172
+                [(('linked_persons', {dyncode.Person:'fullname'}),'=', 'John Doe')]))
173
+

+ 1
- 1
tests/tests_conf.d/lodel2.ini View File

@@ -10,7 +10,7 @@ filename = -
10 10
 context = False
11 11
 
12 12
 [lodel2.editorialmodel]
13
-groups = index_group
13
+groups = 
14 14
 emfile = examples/em_test.pickle
15 15
 dyncode = leapi_dyncode.py
16 16
 editormode = True

Loading…
Cancel
Save