Full-text index all string attributes
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Mon, 17 Oct 2016 14:43:32 +0200
changeset 1848 44879714e928
parent 1847 55b4f1a5d3ec
child 1849 8e833a9015e2
Full-text index all string attributes A test backported from saem cube put the light on this problem.
schema/seda2.py
test/test_schema.py
xsd2yams.py
--- a/schema/seda2.py	Mon Oct 17 14:42:01 2016 +0200
+++ b/schema/seda2.py	Mon Oct 17 14:43:32 2016 +0200
@@ -37,7 +37,7 @@
                       annotable=True)
 class SEDAComment(EntityType):
     u""""""
-    comment = String()
+    comment = String(fulltextindexed=True)
 
 
 class archive_transfer_comment(RelationDefinition):
@@ -68,7 +68,7 @@
                       annotable=True)
 class SEDAArchivalAgreement(EntityType):
     u""""""
-    archival_agreement = String()
+    archival_agreement = String(fulltextindexed=True)
 
 
 class archive_transfer_archival_agreement(RelationDefinition):
@@ -423,7 +423,7 @@
                       annotable=True)
 class SEDABinaryDataObject(EntityType):
     u""""""
-    filename = String()
+    filename = String(fulltextindexed=True)
     id = String(required=True, description=_('Default identifier that will be used to handle references. This is not necessarily the identifier that will appear in the final sheet.'), constraints=[RQLConstraint('NOT EXISTS(S id I, X id I, S container C, X container C, NOT S identity X)', msg=_('identifier must be unique within a profile'))])
 
 
@@ -551,7 +551,7 @@
                       annotable=True)
 class SEDAServiceLevel(EntityType):
     u""""""
-    service_level = String()
+    service_level = String(fulltextindexed=True)
 
 
 class archive_transfer_service_level(RelationDefinition):
@@ -642,7 +642,7 @@
                       annotable=True)
 class SEDAClassificationRule(EntityType):
     u""""""
-    classification_owner = String()
+    classification_owner = String(fulltextindexed=True)
 
 
 class archive_transfer_classification_rule(RelationDefinition):
@@ -755,7 +755,7 @@
                       annotable=True)
 class SEDAFormatLitteral(EntityType):
     u""""""
-    format_litteral = String()
+    format_litteral = String(fulltextindexed=True)
 
 
 class binary_data_object_format_litteral(RelationDefinition):
@@ -843,7 +843,7 @@
                       annotable=True)
 class SEDACreatingApplicationName(EntityType):
     u""""""
-    creating_application_name = String()
+    creating_application_name = String(fulltextindexed=True)
 
 
 class binary_data_object_creating_application_name(RelationDefinition):
@@ -859,7 +859,7 @@
                       annotable=True)
 class SEDACreatingApplicationVersion(EntityType):
     u""""""
-    creating_application_version = String()
+    creating_application_version = String(fulltextindexed=True)
 
 
 class binary_data_object_creating_application_version(RelationDefinition):
@@ -890,7 +890,7 @@
                       annotable=True)
 class SEDACreatingOs(EntityType):
     u""""""
-    creating_os = String()
+    creating_os = String(fulltextindexed=True)
 
 
 class binary_data_object_creating_os(RelationDefinition):
@@ -906,7 +906,7 @@
                       annotable=True)
 class SEDACreatingOsVersion(EntityType):
     u""""""
-    creating_os_version = String()
+    creating_os_version = String(fulltextindexed=True)
 
 
 class binary_data_object_creating_os_version(RelationDefinition):
@@ -1505,7 +1505,7 @@
                       annotable=True)
 class SEDArestrictionRuleIdRef(EntityType):
     u""""""
-    restriction_rule_id_ref = String()
+    restriction_rule_id_ref = String(fulltextindexed=True)
 
 
 class content_restriction_rule_id_ref(RelationDefinition):
@@ -1521,7 +1521,7 @@
                       annotable=True)
 class SEDArestrictionValue(EntityType):
     u""""""
-    restriction_value = String()
+    restriction_value = String(fulltextindexed=True)
 
 
 class content_restriction_value(RelationDefinition):
@@ -1561,7 +1561,7 @@
                       annotable=True)
 class SEDATitle(EntityType):
     u""""""
-    title = String()
+    title = String(fulltextindexed=True)
 
 
 class content_title(RelationDefinition):
@@ -1577,7 +1577,7 @@
                       annotable=True)
 class SEDAFilePlanPosition(EntityType):
     u""""""
-    file_plan_position = String()
+    file_plan_position = String(fulltextindexed=True)
 
 
 class content_file_plan_position(RelationDefinition):
@@ -1623,7 +1623,7 @@
                       annotable=True)
 class SEDAArchivalAgencyArchiveUnitIdentifier(EntityType):
     u""""""
-    archival_agency_archive_unit_identifier = String()
+    archival_agency_archive_unit_identifier = String(fulltextindexed=True)
 
 
 class content_archival_agency_archive_unit_identifier(RelationDefinition):
@@ -1639,7 +1639,7 @@
                       annotable=True)
 class SEDAOriginatingAgencyArchiveUnitIdentifier(EntityType):
     u""""""
-    originating_agency_archive_unit_identifier = String()
+    originating_agency_archive_unit_identifier = String(fulltextindexed=True)
 
 
 class content_originating_agency_archive_unit_identifier(RelationDefinition):
@@ -1655,7 +1655,7 @@
                       annotable=True)
 class SEDATransferringAgencyArchiveUnitIdentifier(EntityType):
     u""""""
-    transferring_agency_archive_unit_identifier = String()
+    transferring_agency_archive_unit_identifier = String(fulltextindexed=True)
 
 
 class content_transferring_agency_archive_unit_identifier(RelationDefinition):
@@ -1671,7 +1671,7 @@
                       annotable=True)
 class SEDADescription(EntityType):
     u""""""
-    description = String()
+    description = String(fulltextindexed=True)
 
 
 class content_description(RelationDefinition):
@@ -1711,7 +1711,7 @@
                       annotable=True)
 class SEDADocumentType(EntityType):
     u""""""
-    document_type = String()
+    document_type = String(fulltextindexed=True)
 
 
 class content_document_type(RelationDefinition):
@@ -1775,7 +1775,7 @@
                       annotable=True)
 class SEDAStatus(EntityType):
     u""""""
-    status = String()
+    status = String(fulltextindexed=True)
 
 
 class content_status(RelationDefinition):
@@ -1791,7 +1791,7 @@
                       annotable=True)
 class SEDAVersion(EntityType):
     u""""""
-    version = String()
+    version = String(fulltextindexed=True)
 
 
 class content_version(RelationDefinition):
@@ -1807,7 +1807,7 @@
                       annotable=True)
 class SEDATag(EntityType):
     u""""""
-    tag = String()
+    tag = String(fulltextindexed=True)
 
 
 class content_tag(RelationDefinition):
@@ -1982,7 +1982,7 @@
                       annotable=True)
 class SEDASource(EntityType):
     u""""""
-    source = String()
+    source = String(fulltextindexed=True)
 
 
 class content_source(RelationDefinition):
@@ -2245,7 +2245,7 @@
                       annotable=True)
 class SEDACustodialHistoryItem(EntityType):
     u""""""
-    custodial_history_item = String()
+    custodial_history_item = String(fulltextindexed=True)
 
 
 class content_custodial_history_item(RelationDefinition):
@@ -2276,7 +2276,7 @@
                       annotable=False)
 class SEDAKeywordContent(EntityType):
     u""""""
-    keyword_content = String()
+    keyword_content = String(fulltextindexed=True)
 
 
 class keyword_keyword_content(RelationDefinition):
@@ -2340,7 +2340,7 @@
                       annotable=True)
 class SEDASpatial(EntityType):
     u""""""
-    spatial = String()
+    spatial = String(fulltextindexed=True)
 
 
 class content_spatial(RelationDefinition):
@@ -2356,7 +2356,7 @@
                       annotable=True)
 class SEDATemporal(EntityType):
     u""""""
-    temporal = String()
+    temporal = String(fulltextindexed=True)
 
 
 class content_temporal(RelationDefinition):
@@ -2372,7 +2372,7 @@
                       annotable=True)
 class SEDAJuridictional(EntityType):
     u""""""
-    juridictional = String()
+    juridictional = String(fulltextindexed=True)
 
 
 class content_juridictional(RelationDefinition):
--- a/test/test_schema.py	Mon Oct 17 14:42:01 2016 +0200
+++ b/test/test_schema.py	Mon Oct 17 14:43:32 2016 +0200
@@ -21,7 +21,7 @@
 from cubicweb.devtools.testlib import CubicWebTC
 from cubicweb.schema import ERQLExpression, RRQLExpression
 
-from testutils import create_archive_unit, create_transfer_to_bdo
+from testutils import create_archive_unit, create_data_object, create_transfer_to_bdo
 
 
 class SchemaTC(CubicWebTC):
@@ -126,7 +126,6 @@
                              'X container C'.format(action=action))
 
     def test_rule_default_cardinality(self):
-
         with self.admin_access.client_cnx() as cnx:
             transfer = cnx.create_entity('SEDAArchiveTransfer', title=u'test profile')
             for rule_type in ('access', 'appraisal'):
@@ -140,6 +139,25 @@
                 start_date = cnx.create_entity('SEDAStartDate', seda_start_date=rule_rule)
                 self.assertEqual(start_date.user_cardinality, '1')
 
+    def test_fti(self):
+        # "Reverse" text to be searched in order not to be troubled by other
+        # entities that may live in the DB (e.g. Concepts) with similar text.
+        with self.admin_access.client_cnx() as cnx:
+            transfer = cnx.create_entity('SEDAArchiveTransfer', title=u'Profile')
+            unit, unit_alt, unit_alt_seq = create_archive_unit(transfer)
+            content = cnx.create_entity('SEDAContent', seda_content=unit_alt_seq)
+            cnx.create_entity('SEDATitle', seda_title=content, title=u'transfer name'[::-1])
+            cnx.create_entity('SEDAAccessRule', seda_access_rule=unit_alt_seq,
+                              user_annotation=u'some annotation'[::-1])
+            create_data_object(transfer, id=u"bdo1", filename=u'fixed.txt'[::-1])
+            cnx.commit()
+
+            for search in ('name', 'annotation', 'fixed'):
+                with self.subTest(search=search):
+                    rset = cnx.execute('Any X WHERE X has_text %(search)s',
+                                       {'search': search[::-1]})
+                    self.assertEqual([r for r, in rset.rows], [transfer.eid])
+
 
 class SecurityTC(CubicWebTC):
 
--- a/xsd2yams.py	Mon Oct 17 14:42:01 2016 +0200
+++ b/xsd2yams.py	Mon Oct 17 14:43:32 2016 +0200
@@ -462,6 +462,8 @@
                         "RQLConstraint('NOT EXISTS(S id I, X id I, S container C, X container C, "
                         "NOT S identity X)', msg=_('identifier must be unique within a profile'))"
                         "]")
+            elif attrtype == 'String':
+                args = 'fulltextindexed=True'
             code += '    {0} = {1}({2})\n'.format(attrname, attrtype, args)
         return code + '\n\n'