[sql generation] fti_need_distinct quere was not anymore used, potentially causing duplicates on has_text queries with sqlite backend stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Tue, 09 Mar 2010 10:48:46 +0100
branchstable
changeset 4836 3e3c4917e94e
parent 4828 3e173d598cad
child 4837 54969eec48eb
[sql generation] fti_need_distinct quere was not anymore used, potentially causing duplicates on has_text queries with sqlite backend
server/sources/native.py
server/sources/rql2sql.py
server/test/unittest_rql2sql.py
--- a/server/sources/native.py	Mon Mar 08 09:05:17 2010 +0100
+++ b/server/sources/native.py	Tue Mar 09 10:48:46 2010 +0100
@@ -149,9 +149,6 @@
         self.authentifiers = [LoginPasswordAuthentifier(self)]
         AbstractSource.__init__(self, repo, appschema, source_config,
                                 *args, **kwargs)
-        # sql generator
-        self._rql_sqlgen = self.sqlgen_class(appschema, self.dbhelper,
-                                             self.encoding, ATTR_MAP.copy())
         # full text index helper
         self.do_fti = not repo.config['delay-full-text-indexation']
         if self.do_fti:
@@ -161,6 +158,11 @@
             self.dbhelper.fti_table = self.indexer.table
             self.dbhelper.fti_restriction_sql = self.indexer.restriction_sql
             self.dbhelper.fti_need_distinct_query = self.indexer.need_distinct
+        else:
+            self.dbhelper.fti_need_distinct_query = False
+        # sql generator
+        self._rql_sqlgen = self.sqlgen_class(appschema, self.dbhelper,
+                                             self.encoding, ATTR_MAP.copy())
         # sql queries cache
         self._cache = Cache(repo.config['rql-cache-size'])
         self._temp_table_data = {}
--- a/server/sources/rql2sql.py	Mon Mar 08 09:05:17 2010 +0100
+++ b/server/sources/rql2sql.py	Tue Mar 09 10:48:46 2010 +0100
@@ -341,6 +341,9 @@
                             }
         if not self.dbms_helper.union_parentheses_support:
             self.union_sql = self.noparen_union_sql
+        if self.dbms_helper.fti_need_distinct_query:
+            self.__union_sql = self.union_sql
+            self.union_sql = self.has_text_need_distinct_union_sql
         self._lock = threading.Lock()
         if attrmap is None:
             attrmap = {}
@@ -374,6 +377,12 @@
         finally:
             self._lock.release()
 
+    def has_text_need_distinct_union_sql(self, union, needalias=False):
+        if getattr(union, 'has_text_query', False):
+            for select in union.children:
+                select.need_distinct = True
+        return self.__union_sql(union, needalias)
+
     def union_sql(self, union, needalias=False): # pylint: disable-msg=E0202
         if len(union.children) == 1:
             return self.select_sql(union.children[0], needalias)
--- a/server/test/unittest_rql2sql.py	Mon Mar 08 09:05:17 2010 +0100
+++ b/server/test/unittest_rql2sql.py	Tue Mar 09 10:48:46 2010 +0100
@@ -1481,26 +1481,26 @@
     def test_has_text(self):
         for t in self._parse((
             ('Any X WHERE X has_text "toto tata"',
-             """SELECT appears0.uid
+             """SELECT DISTINCT appears0.uid
 FROM appears AS appears0
 WHERE appears0.word_id IN (SELECT word_id FROM word WHERE word in ('toto', 'tata'))"""),
 
             ('Any X WHERE X has_text %(text)s',
-             """SELECT appears0.uid
+             """SELECT DISTINCT appears0.uid
 FROM appears AS appears0
 WHERE appears0.word_id IN (SELECT word_id FROM word WHERE word in ('hip', 'hop', 'momo'))"""),
 
             ('Personne X WHERE X has_text "toto tata"',
-             """SELECT _X.eid
+             """SELECT DISTINCT _X.eid
 FROM appears AS appears0, entities AS _X
 WHERE appears0.word_id IN (SELECT word_id FROM word WHERE word in ('toto', 'tata')) AND appears0.uid=_X.eid AND _X.type='Personne'"""),
 
             ('Any X WHERE X has_text "toto tata", X name "tutu", X is IN (Basket,Folder)',
-             """SELECT _X.cw_eid
+             """SELECT DISTINCT _X.cw_eid
 FROM appears AS appears0, cw_Basket AS _X
 WHERE appears0.word_id IN (SELECT word_id FROM word WHERE word in ('toto', 'tata')) AND appears0.uid=_X.cw_eid AND _X.cw_name=tutu
-UNION ALL
-SELECT _X.cw_eid
+UNION
+SELECT DISTINCT _X.cw_eid
 FROM appears AS appears0, cw_Folder AS _X
 WHERE appears0.word_id IN (SELECT word_id FROM word WHERE word in ('toto', 'tata')) AND appears0.uid=_X.cw_eid AND _X.cw_name=tutu
 """),