From d47df833fbd52292d91421b370df0e3bd1932b06 Mon Sep 17 00:00:00 2001 From: Kazuhiko Shiozaki <kazuhiko@nexedi.com> Date: Thu, 23 Oct 2014 15:54:43 +0200 Subject: [PATCH] use fulltext search in title and description. * to quickly setup catalog_full_text table, you can use the following SQL. REPLACE INTO catalog_full_text SELECT uid, title, description FROM catalog; * non fulltext queries like '=abc', '>abc', '%abc%' are supported. * now erp5_full_text_mroonga_catalog is used for unit tests thus I recommend using it instead of erp5_full_text_myisam_catalog. * to migrate existing MyISAM full_text table into Mroonga, you can use the following SQL. ALTER TABLE full_text DROP KEY SearchableText, ENGINE = mroonga, ADD FULLTEXT KEY SearchableText (`SearchableText`) COMMENT 'parser "TokenBigramSplitSymbolAlpha"'; * fulltext search score is no longer provided as (column_name) but now provided as (column_name)__score__. * (category)_title, like source_title, related keys are automatically generated. (category)_description keys as well. --- .../related_key_list.xml | 8 +- .../bt/template_catalog_related_key_list | 8 +- ...gZuite_createAccountingTransactionList.xml | 9 +- ...ountingTransactionListSalesAndPayments.xml | 7 +- ...teAccountingTransactionListWithPersons.xml | 9 +- .../AccountingZuite_reset.xml | 3 +- .../related_key_list.xml | 6 +- .../bt/template_catalog_related_key_list | 6 +- bt5/erp5_bearer_token/bt/test_dependency_list | 2 +- .../bt/test_dependency_list | 2 +- .../bt/test_dependency_list | 2 +- .../bt/test_dependency_list | 2 +- .../bt/test_dependency_list | 2 +- .../bt/test_dependency_list | 2 +- ...entTranslationSearchQuery.catalog_keys.xml | 2 - ...alog_makeContentTranslationSearchQuery.xml | 84 --------- .../scriptable_key_list.xml | 2 +- .../bt/template_catalog_scriptable_key_list | 2 +- .../related_key_list.xml | 2 +- .../bt/template_catalog_related_key_list | 2 +- .../Base_getDemoSMBBusinessTemplateList.xml | 2 +- .../Base_getUngBusinessTemplateList.xml | 2 +- .../bt/test_dependency_list | 2 +- .../full_text_key_list.xml | 4 - .../SQLCatalog_deferFullTextIndexActivity.xml | 5 +- .../z0_drop_catalog_fulltext.catalog_keys.xml | 5 + .../z0_drop_catalog_fulltext.xml | 70 ++++++++ ...ncatalog_catalog_fulltext.catalog_keys.xml | 5 + .../z0_uncatalog_catalog_fulltext.xml | 68 ++++++++ ...log_catalog_fulltext_list.catalog_keys.xml | 5 + .../z_catalog_catalog_fulltext_list.xml | 80 +++++++++ .../z_catalog_fulltext_list.xml | 27 +-- ...z_create_catalog_fulltext.catalog_keys.xml | 5 + .../z_create_catalog_fulltext.xml | 82 +++++++++ .../z_create_content_translation.xml | 2 +- .../erp5_mysql_innodb/z_create_fulltext.xml | 2 +- .../related_key_list.xml | 10 ++ .../result_table_list.xml | 1 + .../search_key_list.xml | 8 + .../bt/template_catalog_full_text_key_list | 2 - .../bt/template_catalog_method_id_list | 4 + .../bt/template_catalog_related_key_list | 8 + .../bt/template_catalog_result_table_list | 1 + .../bt/template_catalog_search_key_list | 6 + .../full_text_key_list.xml | 6 +- .../SQLCatalog_deferFullTextIndexActivity.xml | 5 +- .../z0_drop_catalog_fulltext.catalog_keys.xml | 5 + .../z0_drop_catalog_fulltext.xml | 70 ++++++++ ...ncatalog_catalog_fulltext.catalog_keys.xml | 5 + .../z0_uncatalog_catalog_fulltext.xml | 68 ++++++++ ...log_catalog_fulltext_list.catalog_keys.xml | 5 + .../z_catalog_catalog_fulltext_list.xml | 80 +++++++++ .../z_catalog_fulltext_list.xml | 27 +-- ...z_create_catalog_fulltext.catalog_keys.xml | 5 + .../z_create_catalog_fulltext.xml | 82 +++++++++ .../related_key_list.xml | 10 ++ .../result_table_list.xml | 1 + .../bt/template_catalog_full_text_key_list | 6 +- .../bt/template_catalog_method_id_list | 4 + .../bt/template_catalog_related_key_list | 8 + .../bt/template_catalog_result_table_list | 1 + bt5/erp5_ingestion/bt/test_dependency_list | 2 +- .../related_key_list.xml | 2 +- .../bt/template_catalog_related_key_list | 2 +- .../testTopSearchBoxClicking.xml | 4 +- .../bt/test_dependency_list | 2 +- .../bt/test_dependency_list | 2 +- bt5/erp5_pdf_merge/bt/test_dependency_list | 2 +- .../bt/test_dependency_list | 2 +- bt5/erp5_safeimage/bt/test_dependency_list | 2 +- .../bt/test_dependency_list | 2 +- .../bt/test_dependency_list | 2 +- ...ocument.erp5.ERP5ScalabilityDistributor.py | 9 +- bt5/erp5_test_result/bt/test_dependency_list | 2 +- .../testOxatisSynchronization.py | 2 +- ...ltiRelationFieldSearchDialogChangePage.xml | 10 +- .../testSimpleRelationFieldWithListbox.xml | 2 +- .../testSimpleRequiredRelationField.xml | 4 +- bt5/erp5_upgrader/bt/test_dependency_list | 2 +- ...emplateTool_checkPreUpgradeConsistency.xml | 2 +- bt5/erp5_web_shacache/bt/test_dependency_list | 2 +- bt5/erp5_web_shadir/bt/test_dependency_list | 2 +- bt5/erp5_web_ung_core/bt/test_dependency_list | 2 +- bt5/erp5_web_ung_role/bt/test_dependency_list | 2 +- .../bt/test_dependency_list | 2 +- bt5/networkcache_erp5/bt/test_dependency_list | 2 +- .../bt/test_dependency_list | 2 +- .../ERP5ProjectUnitTestDistributor.py | 28 ++- product/ERP5/Tool/TaskDistributionTool.py | 7 +- .../erp5_core/bt/test_dependency_list | 2 +- .../SQLCatalog_makeTranslatedTitleQuery.xml | 8 +- product/ERP5/tests/testCRM.py | 4 +- product/ERP5/tests/testERP5Coordinate.py | 2 +- product/ERP5/tests/testERP5Credential.py | 2 +- product/ERP5/tests/testERP5eGov.py | 2 +- .../tests/testFunctionalRunMyDocSample.py | 2 +- product/ERP5/tests/testI18NSearch.py | 23 ++- product/ERP5/tests/testKM.py | 2 +- product/ERP5/tests/testSpellChecking.py | 2 +- product/ERP5/tests/testTemplateTool.py | 4 +- product/ERP5Catalog/CatalogTool.py | 22 ++- product/ERP5Catalog/tests/testArchive.py | 2 +- product/ERP5Catalog/tests/testERP5Catalog.py | 165 +++++++++--------- .../testERP5CatalogSecurityUidOptimization.py | 2 +- .../tests/ConfiguratorTestMixin.py | 2 +- .../tests/testConfiguratorItem.py | 2 +- .../tests/testConfiguratorTool.py | 2 +- .../tests/testFunctionalConfigurator.py | 2 +- product/ERP5Form/Tool/SelectionTool.py | 3 +- product/ERP5OOo/tests/testDms.py | 10 +- product/ERP5OOo/tests/testOOoDynamicStyle.py | 2 +- product/ERP5TioSafe/tests/testTioSafeMixin.py | 2 +- .../tests/testFunctionalAnonymousSelection.py | 2 +- product/ERP5Type/tests/testFunctionalCore.py | 2 +- product/ERP5Type/tests/testFunctionalKM.py | 2 +- .../testFunctionalStandaloneUserTutorial.py | 2 +- .../ZMySQLDA/tests/testDeferredConnection.py | 2 +- .../Operator/ComparisonOperator.py | 54 +++++- product/ZSQLCatalog/Query/RelatedQuery.py | 6 +- product/ZSQLCatalog/SQLExpression.py | 3 + product/ZSQLCatalog/SearchKey/FullTextKey.py | 36 +++- .../SearchKey/MroongaBooleanFullTextKey.py | 40 +++++ .../SearchKey/MroongaFullTextKey.py | 92 ++++++++++ product/ZSQLCatalog/tests/testSQLCatalog.py | 94 ++++++---- 124 files changed, 1291 insertions(+), 375 deletions(-) delete mode 100644 bt5/erp5_content_translation/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_makeContentTranslationSearchQuery.catalog_keys.xml delete mode 100644 bt5/erp5_content_translation/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_makeContentTranslationSearchQuery.xml delete mode 100644 bt5/erp5_full_text_mroonga_catalog/CatalogFullTextKeyTemplateItem/full_text_key_list.xml create mode 100644 bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_catalog_fulltext.catalog_keys.xml create mode 100644 bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_catalog_fulltext.xml create mode 100644 bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_catalog_fulltext.catalog_keys.xml create mode 100644 bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_catalog_fulltext.xml create mode 100644 bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_catalog_fulltext_list.catalog_keys.xml create mode 100644 bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_catalog_fulltext_list.xml create mode 100644 bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_catalog_fulltext.catalog_keys.xml create mode 100644 bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_catalog_fulltext.xml create mode 100644 bt5/erp5_full_text_mroonga_catalog/CatalogRelatedKeyTemplateItem/related_key_list.xml create mode 100644 bt5/erp5_full_text_mroonga_catalog/CatalogSearchKeyTemplateItem/search_key_list.xml delete mode 100644 bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_full_text_key_list create mode 100644 bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_related_key_list create mode 100644 bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_search_key_list create mode 100644 bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_catalog_fulltext.catalog_keys.xml create mode 100644 bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_catalog_fulltext.xml create mode 100644 bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_catalog_fulltext.catalog_keys.xml create mode 100644 bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_catalog_fulltext.xml create mode 100644 bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_catalog_fulltext_list.catalog_keys.xml create mode 100644 bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_catalog_fulltext_list.xml create mode 100644 bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_catalog_fulltext.catalog_keys.xml create mode 100644 bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_catalog_fulltext.xml create mode 100644 bt5/erp5_full_text_myisam_catalog/CatalogRelatedKeyTemplateItem/related_key_list.xml create mode 100644 bt5/erp5_full_text_myisam_catalog/bt/template_catalog_related_key_list create mode 100644 product/ZSQLCatalog/SearchKey/MroongaBooleanFullTextKey.py create mode 100644 product/ZSQLCatalog/SearchKey/MroongaFullTextKey.py diff --git a/bt5/erp5_accounting/CatalogRelatedKeyTemplateItem/related_key_list.xml b/bt5/erp5_accounting/CatalogRelatedKeyTemplateItem/related_key_list.xml index debd7365b9..7016a85a28 100644 --- a/bt5/erp5_accounting/CatalogRelatedKeyTemplateItem/related_key_list.xml +++ b/bt5/erp5_accounting/CatalogRelatedKeyTemplateItem/related_key_list.xml @@ -1,10 +1,10 @@ <key_list> <key>accounting_transaction_line_node_uid | stock/node_uid/z_related_accounting_transaction_stock_line</key> <key>accounting_transaction_line_total_price | stock/total_price/z_related_accounting_transaction_stock_line</key> - <key>accounting_transaction_mirror_section_title | catalog/title/z_related_accounting_transaction_mirror_section</key> - <key>accounting_transaction_payment_title | catalog/title/z_related_accounting_transaction_payment</key> - <key>accounting_transaction_project_title | catalog/title/z_related_accounting_transaction_project</key> - <key>accounting_transaction_section_title | catalog/title/z_related_accounting_transaction_section</key> + <key>accounting_transaction_mirror_section_title | catalog_full_text/title/z_related_accounting_transaction_mirror_section</key> + <key>accounting_transaction_payment_title | catalog_full_text/title/z_related_accounting_transaction_payment</key> + <key>accounting_transaction_project_title | catalog_full_text/title/z_related_accounting_transaction_project</key> + <key>accounting_transaction_section_title | catalog_full_text/title/z_related_accounting_transaction_section</key> <key>preferred_gap_id | category,catalog/id/z_related_preferred_gap</key> <key>preferred_gap_strict_membership_id | category,catalog/id/z_related_strict_membership_preferred_gap</key> </key_list> \ No newline at end of file diff --git a/bt5/erp5_accounting/bt/template_catalog_related_key_list b/bt5/erp5_accounting/bt/template_catalog_related_key_list index dcde7ac950..1f5a0ffbcf 100644 --- a/bt5/erp5_accounting/bt/template_catalog_related_key_list +++ b/bt5/erp5_accounting/bt/template_catalog_related_key_list @@ -1,8 +1,8 @@ preferred_gap_id | category,catalog/id/z_related_preferred_gap preferred_gap_strict_membership_id | category,catalog/id/z_related_strict_membership_preferred_gap -accounting_transaction_mirror_section_title | catalog/title/z_related_accounting_transaction_mirror_section -accounting_transaction_section_title | catalog/title/z_related_accounting_transaction_section -accounting_transaction_project_title | catalog/title/z_related_accounting_transaction_project -accounting_transaction_payment_title | catalog/title/z_related_accounting_transaction_payment +accounting_transaction_mirror_section_title | catalog_full_text/title/z_related_accounting_transaction_mirror_section +accounting_transaction_section_title | catalog_full_text/title/z_related_accounting_transaction_section +accounting_transaction_project_title | catalog_full_text/title/z_related_accounting_transaction_project +accounting_transaction_payment_title | catalog_full_text/title/z_related_accounting_transaction_payment accounting_transaction_line_node_uid | stock/node_uid/z_related_accounting_transaction_stock_line accounting_transaction_line_total_price | stock/total_price/z_related_accounting_transaction_stock_line \ No newline at end of file diff --git a/bt5/erp5_accounting_ui_test/SkinTemplateItem/portal_skins/erp5_accounting_ui_test/AccountingZuite_createAccountingTransactionList.xml b/bt5/erp5_accounting_ui_test/SkinTemplateItem/portal_skins/erp5_accounting_ui_test/AccountingZuite_createAccountingTransactionList.xml index 21b349b51b..effbdeb77c 100644 --- a/bt5/erp5_accounting_ui_test/SkinTemplateItem/portal_skins/erp5_accounting_ui_test/AccountingZuite_createAccountingTransactionList.xml +++ b/bt5/erp5_accounting_ui_test/SkinTemplateItem/portal_skins/erp5_accounting_ui_test/AccountingZuite_createAccountingTransactionList.xml @@ -53,6 +53,7 @@ <value> <string encoding="cdata"><![CDATA[ from DateTime import DateTime\n +from Products.ZSQLCatalog.SQLCatalog import SimpleQuery\n \n # params\n section_title = \'My Organisation\'\n @@ -90,7 +91,7 @@ if 1:\n def getAccountByTitle(title):\n account_list = [x.getObject().getRelativeUrl() for x in\n portal.portal_catalog(portal_type=\'Account\',\n - title=title)]\n + title=SimpleQuery(title=title, comparison_operator=\'=\'))]\n assert len(account_list) == 1, \\\n \'%d account with title "%s"\' % (len(account_list), title)\n return account_list[0]\n @@ -98,7 +99,7 @@ def getAccountByTitle(title):\n def getOrganisationByTitle(title):\n document_list = [x.getObject().getRelativeUrl() for x in\n portal.portal_catalog(portal_type=\'Organisation\',\n - title=title)]\n + title=SimpleQuery(title=title, comparison_operator=\'=\'))]\n assert len(document_list) == 1, \\\n \'%d organisation with title "%s"\' % (len(document_list), title)\n return document_list[0]\n @@ -109,14 +110,14 @@ euro_resource = \'currency_module/euro\'\n def getBankAccountByTitle(title):\n document_list = [x.getObject().getRelativeUrl() for x in\n portal.portal_catalog(portal_type=\'Bank Account\',\n - title=title)]\n + title=SimpleQuery(title=title, comparison_operator=\'=\'))]\n assert len(document_list) == 1, \\\n \'%d Bank Account with title "%s"\' % (len(document_list), title)\n return document_list[0]\n \n product_list = [o.getObject() for o in portal.portal_catalog(\n portal_type=\'Product\',\n - title=\'Dummy Product for testing\')]\n + title=SimpleQuery(title=\'Dummy Product for testing\', comparison_operator=\'=\'))]\n if product_list:\n product = product_list[0]\n else:\n diff --git a/bt5/erp5_accounting_ui_test/SkinTemplateItem/portal_skins/erp5_accounting_ui_test/AccountingZuite_createAccountingTransactionListSalesAndPayments.xml b/bt5/erp5_accounting_ui_test/SkinTemplateItem/portal_skins/erp5_accounting_ui_test/AccountingZuite_createAccountingTransactionListSalesAndPayments.xml index 0e6934a163..3f973fb2a2 100644 --- a/bt5/erp5_accounting_ui_test/SkinTemplateItem/portal_skins/erp5_accounting_ui_test/AccountingZuite_createAccountingTransactionListSalesAndPayments.xml +++ b/bt5/erp5_accounting_ui_test/SkinTemplateItem/portal_skins/erp5_accounting_ui_test/AccountingZuite_createAccountingTransactionListSalesAndPayments.xml @@ -53,6 +53,7 @@ <value> <string encoding="cdata"><![CDATA[ from DateTime import DateTime\n +from Products.ZSQLCatalog.SQLCatalog import SimpleQuery\n \n # params\n section_title = \'My Organisation\'\n @@ -80,7 +81,7 @@ if 1:\n def getAccountByTitle(title):\n account_list = [x.getObject().getRelativeUrl() for x in\n portal.portal_catalog(portal_type=\'Account\',\n - title=title)]\n + title=SimpleQuery(title=title, comparison_operator=\'=\'))]\n assert len(account_list) == 1, \\\n \'%d account with title "%s"\' % (len(account_list), title)\n return account_list[0]\n @@ -88,7 +89,7 @@ def getAccountByTitle(title):\n def getOrganisationByTitle(title):\n document_list = [x.getObject().getRelativeUrl() for x in\n portal.portal_catalog(portal_type=\'Organisation\',\n - title=title)]\n + title=SimpleQuery(title=title, comparison_operator=\'=\'))]\n assert len(document_list) == 1, \\\n \'%d organisation with title "%s"\' % (len(document_list), title)\n return document_list[0]\n @@ -106,7 +107,7 @@ euro_resource = getCurrencyByReference(\'EUR\')\n def getBankAccountByTitle(title):\n document_list = [x.getObject().getRelativeUrl() for x in\n portal.portal_catalog(portal_type=\'Bank Account\',\n - title=title)]\n + title=SimpleQuery(title=title, comparison_operator=\'=\'))]\n assert len(document_list) == 1, \\\n \'%d Bank Account with title "%s"\' % (len(document_list), title)\n return document_list[0]\n diff --git a/bt5/erp5_accounting_ui_test/SkinTemplateItem/portal_skins/erp5_accounting_ui_test/AccountingZuite_createAccountingTransactionListWithPersons.xml b/bt5/erp5_accounting_ui_test/SkinTemplateItem/portal_skins/erp5_accounting_ui_test/AccountingZuite_createAccountingTransactionListWithPersons.xml index 14e0a758d8..2d27b310af 100644 --- a/bt5/erp5_accounting_ui_test/SkinTemplateItem/portal_skins/erp5_accounting_ui_test/AccountingZuite_createAccountingTransactionListWithPersons.xml +++ b/bt5/erp5_accounting_ui_test/SkinTemplateItem/portal_skins/erp5_accounting_ui_test/AccountingZuite_createAccountingTransactionListWithPersons.xml @@ -58,6 +58,7 @@ business_process = \'business_process_module/erp5_default_business_process\'\n portal = context.getPortalObject()\n accounting_module = portal.accounting_module\n from DateTime import DateTime\n +from Products.ZSQLCatalog.SQLCatalog import SimpleQuery\n year = 2005\n \n # if the previous test didn\'t change input data, no need to recreate content\n @@ -82,7 +83,7 @@ if 1:\n def getAccountByTitle(title):\n account_list = [x.getObject().getRelativeUrl() for x in\n portal.portal_catalog(portal_type=\'Account\',\n - title=title)]\n + title=SimpleQuery(title=title, comparison_operator=\'=\'))]\n assert len(account_list) == 1, \\\n \'%d account with title "%s"\' % (len(account_list), title)\n return account_list[0]\n @@ -90,7 +91,7 @@ def getAccountByTitle(title):\n def getOrganisationByTitle(title):\n document_list = [x.getObject().getRelativeUrl() for x in\n portal.portal_catalog(portal_type=\'Organisation\',\n - title=title)]\n + title=SimpleQuery(title=title, comparison_operator=\'=\'))]\n assert len(document_list) == 1, \\\n \'%d organisation with title "%s"\' % (len(document_list), title)\n return document_list[0]\n @@ -99,7 +100,7 @@ section = getOrganisationByTitle(section_title)\n def getPersonByTitle(title):\n document_list = [x.getObject().getRelativeUrl() for x in\n portal.portal_catalog(portal_type=\'Person\',\n - title=title)]\n + title=SimpleQuery(title=title, comparison_operator=\'=\'))]\n assert len(document_list) == 1, \\\n \'%d person with title "%s"\' % (len(document_list), title)\n return document_list[0]\n @@ -116,7 +117,7 @@ euro_resource = getCurrencyByReference(\'EUR\')\n def getBankAccountByTitle(title):\n document_list = [x.getObject().getRelativeUrl() for x in\n portal.portal_catalog(portal_type=\'Bank Account\',\n - title=title)]\n + title=SimpleQuery(title=title, comparison_operator=\'=\'))]\n assert len(document_list) == 1, \\\n \'%d Bank Account with title "%s"\' % (len(document_list), title)\n return document_list[0]\n diff --git a/bt5/erp5_accounting_ui_test/SkinTemplateItem/portal_skins/erp5_accounting_ui_test/AccountingZuite_reset.xml b/bt5/erp5_accounting_ui_test/SkinTemplateItem/portal_skins/erp5_accounting_ui_test/AccountingZuite_reset.xml index c3932bd98b..e310984696 100644 --- a/bt5/erp5_accounting_ui_test/SkinTemplateItem/portal_skins/erp5_accounting_ui_test/AccountingZuite_reset.xml +++ b/bt5/erp5_accounting_ui_test/SkinTemplateItem/portal_skins/erp5_accounting_ui_test/AccountingZuite_reset.xml @@ -51,6 +51,7 @@ <item> <key> <string>_body</string> </key> <value> <string>portal = context.getPortalObject()\n +from Products.ZSQLCatalog.SQLCatalog import SimpleQuery\n \n # validate rules\n for rule in portal.portal_rules.objectValues():\n @@ -129,7 +130,7 @@ stool.setSelectionColumns(\'account_module_selection\',\n \n # delete the "dummy account" we create in test_account_gap_parallel_list_field\n dummy_account_list = portal.account_module.searchFolder(\n - title=\'Dummy Account for UI Test\')\n + title=SimpleQuery(title=\'Dummy Account for UI Test\', comparison_operator=\'=\'))\n if dummy_account_list:\n portal.account_module.manage_delObjects([dummy_account_list[0].getId()])\n \n diff --git a/bt5/erp5_base/CatalogRelatedKeyTemplateItem/related_key_list.xml b/bt5/erp5_base/CatalogRelatedKeyTemplateItem/related_key_list.xml index 59d2ac3ede..08872aafea 100644 --- a/bt5/erp5_base/CatalogRelatedKeyTemplateItem/related_key_list.xml +++ b/bt5/erp5_base/CatalogRelatedKeyTemplateItem/related_key_list.xml @@ -2,8 +2,8 @@ <key>child_address_SearchableText | catalog,full_text/SearchableText/z_related_child_address</key> <key>child_telephone_SearchableText | catalog,full_text/SearchableText/z_related_child_telephone</key> <key>default_email_text | catalog,email/url_string/z_related_default_email</key> - <key>destination_person_title | category,catalog/title/z_related_destination_person</key> + <key>destination_person_title | category,catalog_full_text/title/z_related_destination_person</key> <key>related_resource_use_uid | category,category,catalog,catalog/uid/z_related_resource_use</key> - <key>source_organisation_title | category,catalog/title/z_related_source_organisation</key> - <key>source_person_title | category,catalog/title/z_related_source_person</key> + <key>source_organisation_title | category,catalog_full_text/title/z_related_source_organisation</key> + <key>source_person_title | category,catalog_full_text/title/z_related_source_person</key> </key_list> \ No newline at end of file diff --git a/bt5/erp5_base/bt/template_catalog_related_key_list b/bt5/erp5_base/bt/template_catalog_related_key_list index 95319495c6..faf6e7a859 100644 --- a/bt5/erp5_base/bt/template_catalog_related_key_list +++ b/bt5/erp5_base/bt/template_catalog_related_key_list @@ -1,6 +1,6 @@ -source_organisation_title | category,catalog/title/z_related_source_organisation -source_person_title | category,catalog/title/z_related_source_person -destination_person_title | category,catalog/title/z_related_destination_person +source_organisation_title | category,catalog_full_text/title/z_related_source_organisation +source_person_title | category,catalog_full_text/title/z_related_source_person +destination_person_title | category,catalog_full_text/title/z_related_destination_person default_email_text | catalog,email/url_string/z_related_default_email related_resource_use_uid | category,category,catalog,catalog/uid/z_related_resource_use child_address_SearchableText | catalog,full_text/SearchableText/z_related_child_address diff --git a/bt5/erp5_bearer_token/bt/test_dependency_list b/bt5/erp5_bearer_token/bt/test_dependency_list index 418a1a563a..bff77e32d8 100644 --- a/bt5/erp5_bearer_token/bt/test_dependency_list +++ b/bt5/erp5_bearer_token/bt/test_dependency_list @@ -1 +1 @@ -erp5_full_text_myisam_catalog \ No newline at end of file +erp5_full_text_mroonga_catalog \ No newline at end of file diff --git a/bt5/erp5_configurator_ebusiness_lotse/bt/test_dependency_list b/bt5/erp5_configurator_ebusiness_lotse/bt/test_dependency_list index 418a1a563a..bff77e32d8 100644 --- a/bt5/erp5_configurator_ebusiness_lotse/bt/test_dependency_list +++ b/bt5/erp5_configurator_ebusiness_lotse/bt/test_dependency_list @@ -1 +1 @@ -erp5_full_text_myisam_catalog \ No newline at end of file +erp5_full_text_mroonga_catalog \ No newline at end of file diff --git a/bt5/erp5_configurator_maxma_demo/bt/test_dependency_list b/bt5/erp5_configurator_maxma_demo/bt/test_dependency_list index 8165f76e00..fd4ff5b6e3 100644 --- a/bt5/erp5_configurator_maxma_demo/bt/test_dependency_list +++ b/bt5/erp5_configurator_maxma_demo/bt/test_dependency_list @@ -1,4 +1,4 @@ erp5_core_proxy_field_legacy -erp5_full_text_myisam_catalog +erp5_full_text_mroonga_catalog erp5_base erp5_workflow \ No newline at end of file diff --git a/bt5/erp5_configurator_run_my_doc/bt/test_dependency_list b/bt5/erp5_configurator_run_my_doc/bt/test_dependency_list index 8165f76e00..fd4ff5b6e3 100644 --- a/bt5/erp5_configurator_run_my_doc/bt/test_dependency_list +++ b/bt5/erp5_configurator_run_my_doc/bt/test_dependency_list @@ -1,4 +1,4 @@ erp5_core_proxy_field_legacy -erp5_full_text_myisam_catalog +erp5_full_text_mroonga_catalog erp5_base erp5_workflow \ No newline at end of file diff --git a/bt5/erp5_configurator_standard/bt/test_dependency_list b/bt5/erp5_configurator_standard/bt/test_dependency_list index 418a1a563a..bff77e32d8 100644 --- a/bt5/erp5_configurator_standard/bt/test_dependency_list +++ b/bt5/erp5_configurator_standard/bt/test_dependency_list @@ -1 +1 @@ -erp5_full_text_myisam_catalog \ No newline at end of file +erp5_full_text_mroonga_catalog \ No newline at end of file diff --git a/bt5/erp5_configurator_ung/bt/test_dependency_list b/bt5/erp5_configurator_ung/bt/test_dependency_list index 8165f76e00..fd4ff5b6e3 100644 --- a/bt5/erp5_configurator_ung/bt/test_dependency_list +++ b/bt5/erp5_configurator_ung/bt/test_dependency_list @@ -1,4 +1,4 @@ erp5_core_proxy_field_legacy -erp5_full_text_myisam_catalog +erp5_full_text_mroonga_catalog erp5_base erp5_workflow \ No newline at end of file diff --git a/bt5/erp5_content_translation/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_makeContentTranslationSearchQuery.catalog_keys.xml b/bt5/erp5_content_translation/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_makeContentTranslationSearchQuery.catalog_keys.xml deleted file mode 100644 index a540f9431e..0000000000 --- a/bt5/erp5_content_translation/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_makeContentTranslationSearchQuery.catalog_keys.xml +++ /dev/null @@ -1,2 +0,0 @@ -<catalog_method> -</catalog_method> diff --git a/bt5/erp5_content_translation/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_makeContentTranslationSearchQuery.xml b/bt5/erp5_content_translation/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_makeContentTranslationSearchQuery.xml deleted file mode 100644 index 0f25ec0a9e..0000000000 --- a/bt5/erp5_content_translation/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_makeContentTranslationSearchQuery.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0"?> -<ZopeData> - <record id="1" aka="AAAAAAAAAAE="> - <pickle> - <global name="PythonScript" module="Products.PythonScripts.PythonScript"/> - </pickle> - <pickle> - <dictionary> - <item> - <key> <string>Script_magic</string> </key> - <value> <int>3</int> </value> - </item> - <item> - <key> <string>_bind_names</string> </key> - <value> - <object> - <klass> - <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/> - </klass> - <tuple/> - <state> - <dictionary> - <item> - <key> <string>_asgns</string> </key> - <value> - <dictionary> - <item> - <key> <string>name_container</string> </key> - <value> <string>container</string> </value> - </item> - <item> - <key> <string>name_context</string> </key> - <value> <string>context</string> </value> - </item> - <item> - <key> <string>name_m_self</string> </key> - <value> <string>script</string> </value> - </item> - <item> - <key> <string>name_subpath</string> </key> - <value> <string>traverse_subpath</string> </value> - </item> - </dictionary> - </value> - </item> - </dictionary> - </state> - </object> - </value> - </item> - <item> - <key> <string>_body</string> </key> - <value> <string>from Products.ZSQLCatalog.SQLCatalog import Query, SimpleQuery, AndQuery\n -\n -########### CONFIGURATION ######################################\n -# This is a query for search translated properties of Person #\n -# documents. If you want to get other results. Customise this. # \n -################################################################\n -\n -query = AndQuery(SimpleQuery(**{\'content_translation.translated_text\': value, \'comparison_operator\': \'match\'}),\n - Query(**{\'content_translation.property_name\': \'title\'})\n - )\n -\n -################################################################\n -# Above query must make SQL condition like this. #\n -################################################################\n -# MATCH(content_translation.translated_text) AGAINST({value})\n -# AND content_translation.property_name = \'title\'\n -\n -return query\n -</string> </value> - </item> - <item> - <key> <string>_params</string> </key> - <value> <string>value</string> </value> - </item> - <item> - <key> <string>id</string> </key> - <value> <string>SQLCatalog_makeContentTranslationSearchQuery</string> </value> - </item> - </dictionary> - </pickle> - </record> -</ZopeData> diff --git a/bt5/erp5_content_translation/CatalogScriptableKeyTemplateItem/scriptable_key_list.xml b/bt5/erp5_content_translation/CatalogScriptableKeyTemplateItem/scriptable_key_list.xml index fbac1af553..be73552308 100644 --- a/bt5/erp5_content_translation/CatalogScriptableKeyTemplateItem/scriptable_key_list.xml +++ b/bt5/erp5_content_translation/CatalogScriptableKeyTemplateItem/scriptable_key_list.xml @@ -1,3 +1,3 @@ <key_list> - <key>content_translation_title | SQLCatalog_makeContentTranslationSearchQuery</key> + <key>content_translation_title | SQLCatalog_makeTranslatedTitleQuery</key> </key_list> \ No newline at end of file diff --git a/bt5/erp5_content_translation/bt/template_catalog_scriptable_key_list b/bt5/erp5_content_translation/bt/template_catalog_scriptable_key_list index cbacbbd1d7..7544db4c95 100644 --- a/bt5/erp5_content_translation/bt/template_catalog_scriptable_key_list +++ b/bt5/erp5_content_translation/bt/template_catalog_scriptable_key_list @@ -1 +1 @@ -content_translation_title | SQLCatalog_makeContentTranslationSearchQuery \ No newline at end of file +content_translation_title | SQLCatalog_makeTranslatedTitleQuery \ No newline at end of file diff --git a/bt5/erp5_crm/CatalogRelatedKeyTemplateItem/related_key_list.xml b/bt5/erp5_crm/CatalogRelatedKeyTemplateItem/related_key_list.xml index 38675f5f79..b540f4bd62 100644 --- a/bt5/erp5_crm/CatalogRelatedKeyTemplateItem/related_key_list.xml +++ b/bt5/erp5_crm/CatalogRelatedKeyTemplateItem/related_key_list.xml @@ -6,5 +6,5 @@ <key>related_source_or_source_decision_or_destination_or_destination_decision | category,catalog,catalog/uid/z_related_source_or_source_decision_or_destination_or_destination_decision</key> <key>related_source_or_source_section_or_destination_or_destination_section | category,catalog,catalog/uid/z_related_source_or_source_section_or_destination_or_destination_section</key> <key>related_source_section_or_destination_section | category,catalog,catalog/uid/z_related_source_section_or_destination_section</key> - <key>source_organisation_title | category,catalog/title/z_related_source_organisation</key> + <key>source_organisation_title | category,catalog_full_text/title/z_related_source_organisation</key> </key_list> \ No newline at end of file diff --git a/bt5/erp5_crm/bt/template_catalog_related_key_list b/bt5/erp5_crm/bt/template_catalog_related_key_list index 8825e0c679..ea64c18e6d 100644 --- a/bt5/erp5_crm/bt/template_catalog_related_key_list +++ b/bt5/erp5_crm/bt/template_catalog_related_key_list @@ -1,4 +1,4 @@ -source_organisation_title | category,catalog/title/z_related_source_organisation +source_organisation_title | category,catalog_full_text/title/z_related_source_organisation event_causality_ticket_uid | category,catalog,category,catalog/uid/z_related_event_causality_ticket related_source_or_destination | category,catalog,catalog/uid/z_related_source_or_destination related_source_section_or_destination_section | category,catalog,catalog/uid/z_related_source_section_or_destination_section diff --git a/bt5/erp5_demo_smb/SkinTemplateItem/portal_skins/erp5_demo_smb/Base_getDemoSMBBusinessTemplateList.xml b/bt5/erp5_demo_smb/SkinTemplateItem/portal_skins/erp5_demo_smb/Base_getDemoSMBBusinessTemplateList.xml index c72eb11845..0c38b2b833 100644 --- a/bt5/erp5_demo_smb/SkinTemplateItem/portal_skins/erp5_demo_smb/Base_getDemoSMBBusinessTemplateList.xml +++ b/bt5/erp5_demo_smb/SkinTemplateItem/portal_skins/erp5_demo_smb/Base_getDemoSMBBusinessTemplateList.xml @@ -51,7 +51,7 @@ <item> <key> <string>_body</string> </key> <value> <string>return (\'erp5_core_proxy_field_legacy\',\n - \'erp5_full_text_myisam_catalog\',\n + \'erp5_full_text_mroonga_catalog\',\n \'erp5_base\',\n \'erp5_workflow\',\n \'erp5_configurator\',\n diff --git a/bt5/erp5_demo_ung/SkinTemplateItem/portal_skins/erp5_demo_ung/Base_getUngBusinessTemplateList.xml b/bt5/erp5_demo_ung/SkinTemplateItem/portal_skins/erp5_demo_ung/Base_getUngBusinessTemplateList.xml index 4218fc05eb..9fef9538ee 100644 --- a/bt5/erp5_demo_ung/SkinTemplateItem/portal_skins/erp5_demo_ung/Base_getUngBusinessTemplateList.xml +++ b/bt5/erp5_demo_ung/SkinTemplateItem/portal_skins/erp5_demo_ung/Base_getUngBusinessTemplateList.xml @@ -51,7 +51,7 @@ <item> <key> <string>_body</string> </key> <value> <string>return (\'erp5_core_proxy_field_legacy\',\n - \'erp5_full_text_myisam_catalog\',\n + \'erp5_full_text_mroonga_catalog\',\n \'erp5_base\',\n \'erp5_simulation\',\n \'erp5_dhtml_style\',\n diff --git a/bt5/erp5_forum_tutorial/bt/test_dependency_list b/bt5/erp5_forum_tutorial/bt/test_dependency_list index ac2d8e0533..9560d7ad37 100644 --- a/bt5/erp5_forum_tutorial/bt/test_dependency_list +++ b/bt5/erp5_forum_tutorial/bt/test_dependency_list @@ -1,4 +1,4 @@ -erp5_full_text_myisam_catalog +erp5_full_text_mroonga_catalog erp5_base erp5_web erp5_ingestion_mysql_innodb_catalog diff --git a/bt5/erp5_full_text_mroonga_catalog/CatalogFullTextKeyTemplateItem/full_text_key_list.xml b/bt5/erp5_full_text_mroonga_catalog/CatalogFullTextKeyTemplateItem/full_text_key_list.xml deleted file mode 100644 index 662e00e9f7..0000000000 --- a/bt5/erp5_full_text_mroonga_catalog/CatalogFullTextKeyTemplateItem/full_text_key_list.xml +++ /dev/null @@ -1,4 +0,0 @@ -<key_list> - <key>SearchableText</key> - <key>full_text.SearchableText</key> -</key_list> \ No newline at end of file diff --git a/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_deferFullTextIndexActivity.xml b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_deferFullTextIndexActivity.xml index 99f8fa0c33..38959380dd 100644 --- a/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_deferFullTextIndexActivity.xml +++ b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_deferFullTextIndexActivity.xml @@ -68,8 +68,9 @@ for path in path_list:\n try:\n tmp_dict = {}\n for property in property_list:\n - if property == \'SearchableText\':\n - value = obj.SearchableText()\n + getter = getattr(obj, property, None)\n + if getter is not None and callable(getter):\n + value = getter()\n else:\n value = getattr(obj, \'get%s\' % UpperCase(property))()\n tmp_dict[property] = value\n diff --git a/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_catalog_fulltext.catalog_keys.xml b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_catalog_fulltext.catalog_keys.xml new file mode 100644 index 0000000000..b0fe64af00 --- /dev/null +++ b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_catalog_fulltext.catalog_keys.xml @@ -0,0 +1,5 @@ +<catalog_method> + <item key="sql_clear_catalog" type="int"> + <value>1</value> + </item> +</catalog_method> diff --git a/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_catalog_fulltext.xml b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_catalog_fulltext.xml new file mode 100644 index 0000000000..d9dc3890ee --- /dev/null +++ b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_catalog_fulltext.xml @@ -0,0 +1,70 @@ +<?xml version="1.0"?> +<ZopeData> + <record id="1" aka="AAAAAAAAAAE="> + <pickle> + <global name="SQL" module="Products.ZSQLMethods.SQL"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>_col</string> </key> + <value> + <tuple/> + </value> + </item> + <item> + <key> <string>allow_simple_one_argument_traversal</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>arguments_src</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>cache_time_</string> </key> + <value> <int>0</int> </value> + </item> + <item> + <key> <string>class_file_</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>class_name_</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>connection_hook</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>connection_id</string> </key> + <value> <string>erp5_sql_connection</string> </value> + </item> + <item> + <key> <string>id</string> </key> + <value> <string>z0_drop_catalog_fulltext</string> </value> + </item> + <item> + <key> <string>max_cache_</string> </key> + <value> <int>100</int> </value> + </item> + <item> + <key> <string>max_rows_</string> </key> + <value> <int>1000</int> </value> + </item> + <item> + <key> <string>src</string> </key> + <value> <string>DROP TABLE IF EXISTS catalog_full_text</string> </value> + </item> + <item> + <key> <string>title</string> </key> + <value> <string></string> </value> + </item> + </dictionary> + </pickle> + </record> +</ZopeData> diff --git a/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_catalog_fulltext.catalog_keys.xml b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_catalog_fulltext.catalog_keys.xml new file mode 100644 index 0000000000..d29d36d9f0 --- /dev/null +++ b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_catalog_fulltext.catalog_keys.xml @@ -0,0 +1,5 @@ +<catalog_method> + <item key="sql_uncatalog_object" type="int"> + <value>1</value> + </item> +</catalog_method> diff --git a/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_catalog_fulltext.xml b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_catalog_fulltext.xml new file mode 100644 index 0000000000..d9493f4955 --- /dev/null +++ b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_catalog_fulltext.xml @@ -0,0 +1,68 @@ +<?xml version="1.0"?> +<ZopeData> + <record id="1" aka="AAAAAAAAAAE="> + <pickle> + <global name="SQL" module="Products.ZSQLMethods.SQL"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>allow_simple_one_argument_traversal</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>arguments_src</string> </key> + <value> <string>uid</string> </value> + </item> + <item> + <key> <string>cache_time_</string> </key> + <value> <int>0</int> </value> + </item> + <item> + <key> <string>class_file_</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>class_name_</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>connection_hook</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>connection_id</string> </key> + <value> <string>erp5_sql_deferred_connection</string> </value> + </item> + <item> + <key> <string>id</string> </key> + <value> <string>z0_uncatalog_catalog_fulltext</string> </value> + </item> + <item> + <key> <string>max_cache_</string> </key> + <value> <int>100</int> </value> + </item> + <item> + <key> <string>max_rows_</string> </key> + <value> <int>1000</int> </value> + </item> + <item> + <key> <string>src</string> </key> + <value> <string encoding="cdata"><![CDATA[ + +DELETE FROM catalog_full_text WHERE <dtml-sqltest uid op=eq type=int> + +]]></string> </value> + </item> + <item> + <key> <string>title</string> </key> + <value> <string></string> </value> + </item> + </dictionary> + </pickle> + </record> +</ZopeData> diff --git a/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_catalog_fulltext_list.catalog_keys.xml b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_catalog_fulltext_list.catalog_keys.xml new file mode 100644 index 0000000000..c95a68655e --- /dev/null +++ b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_catalog_fulltext_list.catalog_keys.xml @@ -0,0 +1,5 @@ +<catalog_method> + <item key="sql_catalog_object_list" type="int"> + <value>1</value> + </item> +</catalog_method> diff --git a/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_catalog_fulltext_list.xml b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_catalog_fulltext_list.xml new file mode 100644 index 0000000000..06e374fa75 --- /dev/null +++ b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_catalog_fulltext_list.xml @@ -0,0 +1,80 @@ +<?xml version="1.0"?> +<ZopeData> + <record id="1" aka="AAAAAAAAAAE="> + <pickle> + <global name="SQL" module="Products.ZSQLMethods.SQL"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>allow_simple_one_argument_traversal</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>arguments_src</string> </key> + <value> <string>uid\r\n +getTitle\r\n +getDescription</string> </value> + </item> + <item> + <key> <string>cache_time_</string> </key> + <value> <int>0</int> </value> + </item> + <item> + <key> <string>class_file_</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>class_name_</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>connection_hook</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>connection_id</string> </key> + <value> <string>erp5_sql_deferred_connection</string> </value> + </item> + <item> + <key> <string>id</string> </key> + <value> <string>z_catalog_catalog_fulltext_list</string> </value> + </item> + <item> + <key> <string>max_cache_</string> </key> + <value> <int>100</int> </value> + </item> + <item> + <key> <string>max_rows_</string> </key> + <value> <int>1000</int> </value> + </item> + <item> + <key> <string>src</string> </key> + <value> <string encoding="cdata"><![CDATA[ + +REPLACE INTO\n + catalog_full_text (`uid`, `title`, `description`)\n +VALUES\n +<dtml-in prefix="loop" expr="_.range(_.len(uid))">\n +(\n + <dtml-sqlvar expr="uid[loop_item]" type="int">, \n + <dtml-sqlvar expr="getTitle[loop_item]" type="string" optional>,\n + <dtml-sqlvar expr="getDescription[loop_item]" type="string" optional>\n +)<dtml-unless sequence-end>,</dtml-unless>\n +</dtml-in>\n + + +]]></string> </value> + </item> + <item> + <key> <string>title</string> </key> + <value> <string></string> </value> + </item> + </dictionary> + </pickle> + </record> +</ZopeData> diff --git a/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_fulltext_list.xml b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_fulltext_list.xml index fb0ecee42f..1f0e6f1e03 100644 --- a/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_fulltext_list.xml +++ b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_fulltext_list.xml @@ -55,21 +55,16 @@ SearchableText</string> </value> <key> <string>src</string> </key> <value> <string encoding="cdata"><![CDATA[ -DELETE FROM\n - full_text\n -WHERE\n -<dtml-in uid>\n - uid=<dtml-sqlvar sequence-item type="int"><dtml-if sequence-end><dtml-else> OR </dtml-if>\n -</dtml-in>\n -;\n -<dtml-var "\'\\0\'"><dtml-let document_list="[]">\n +<dtml-let document_list="[]" delete_list="[]">\n <dtml-in prefix="loop" expr="_.range(_.len(uid))">\n <dtml-if "SearchableText[loop_item]">\n <dtml-call expr="document_list.append(loop_item)">\n + <dtml-else>\n + <dtml-call expr="delete_list.append(loop_item)">\n </dtml-if>\n </dtml-in>\n <dtml-if expr="_.len(document_list) > 0">\n -INSERT INTO\n +REPLACE INTO\n full_text\n VALUES\n <dtml-in prefix="loop" expr="document_list">\n @@ -79,7 +74,19 @@ VALUES\n )<dtml-unless sequence-end>,</dtml-unless>\n </dtml-in>\n </dtml-if>\n -</dtml-let> + <dtml-if expr="_.len(delete_list) > 0">\n +<dtml-var sql_delimiter>\n +DELETE FROM\n + full_text\n +WHERE uid IN\n +( \n + <dtml-in prefix="loop" expr="delete_list">\n + <dtml-sqlvar expr="uid[loop_item]" type="int"><dtml-unless sequence-end>,</dtml-unless>\n + </dtml-in>\n +)\n + </dtml-if>\n +</dtml-let>\n + ]]></string> </value> </item> diff --git a/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_catalog_fulltext.catalog_keys.xml b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_catalog_fulltext.catalog_keys.xml new file mode 100644 index 0000000000..b0fe64af00 --- /dev/null +++ b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_catalog_fulltext.catalog_keys.xml @@ -0,0 +1,5 @@ +<catalog_method> + <item key="sql_clear_catalog" type="int"> + <value>1</value> + </item> +</catalog_method> diff --git a/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_catalog_fulltext.xml b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_catalog_fulltext.xml new file mode 100644 index 0000000000..3cac0e0afb --- /dev/null +++ b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_catalog_fulltext.xml @@ -0,0 +1,82 @@ +<?xml version="1.0"?> +<ZopeData> + <record id="1" aka="AAAAAAAAAAE="> + <pickle> + <global name="SQL" module="Products.ZSQLMethods.SQL"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>_col</string> </key> + <value> + <tuple/> + </value> + </item> + <item> + <key> <string>allow_simple_one_argument_traversal</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>arguments_src</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>cache_time_</string> </key> + <value> <int>0</int> </value> + </item> + <item> + <key> <string>class_file_</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>class_name_</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>connection_hook</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>connection_id</string> </key> + <value> <string>erp5_sql_connection</string> </value> + </item> + <item> + <key> <string>id</string> </key> + <value> <string>z_create_catalog_fulltext</string> </value> + </item> + <item> + <key> <string>max_cache_</string> </key> + <value> <int>100</int> </value> + </item> + <item> + <key> <string>max_rows_</string> </key> + <value> <int>1000</int> </value> + </item> + <item> + <key> <string>src</string> </key> + <value> <string># Host:\n +# Database: test\n +# Table: \'catalog_full_text\'\n +#\n +CREATE TABLE `catalog_full_text` (\n + `uid` BIGINT UNSIGNED NOT NULL,\n + `title` varchar(255) default \'\',\n + `description` text,\n + PRIMARY KEY (`uid`),\n + FULLTEXT `title` (`title`) COMMENT \'parser "TokenBigramSplitSymbolAlpha"\',\n + FULLTEXT `description` (`description`) COMMENT \'parser "TokenBigramSplitSymbolAlpha"\'\n +) ENGINE=mroonga;\n +</string> </value> + </item> + <item> + <key> <string>title</string> </key> + <value> <string></string> </value> + </item> + </dictionary> + </pickle> + </record> +</ZopeData> diff --git a/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_content_translation.xml b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_content_translation.xml index 6fca1aaac5..7b1a162804 100644 --- a/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_content_translation.xml +++ b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_content_translation.xml @@ -64,7 +64,7 @@ `content_language` VARBINARY(100),\n `translated_text` TEXT,\n PRIMARY KEY (`uid`, `property_name`, `content_language`),\n - FULLTEXT KEY (`translated_text`)\n + FULLTEXT KEY (`translated_text`) COMMENT \'parser "TokenBigramSplitSymbolAlpha"\'\n ) ENGINE=mroonga;\n </string> </value> </item> diff --git a/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_fulltext.xml b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_fulltext.xml index c0ae591177..bcdfe1141f 100644 --- a/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_fulltext.xml +++ b/bt5/erp5_full_text_mroonga_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_fulltext.xml @@ -66,7 +66,7 @@ CREATE TABLE `full_text` (\n `uid` BIGINT UNSIGNED NOT NULL,\n `SearchableText` MEDIUMTEXT,\n PRIMARY KEY (`uid`),\n - FULLTEXT `SearchableText` (`SearchableText`)\n + FULLTEXT `SearchableText` (`SearchableText`) COMMENT \'parser "TokenBigramSplitSymbolAlpha"\'\n ) ENGINE=mroonga;\n </string> </value> </item> diff --git a/bt5/erp5_full_text_mroonga_catalog/CatalogRelatedKeyTemplateItem/related_key_list.xml b/bt5/erp5_full_text_mroonga_catalog/CatalogRelatedKeyTemplateItem/related_key_list.xml new file mode 100644 index 0000000000..2ced6f2d72 --- /dev/null +++ b/bt5/erp5_full_text_mroonga_catalog/CatalogRelatedKeyTemplateItem/related_key_list.xml @@ -0,0 +1,10 @@ +<key_list> + <key>career_skill_title | category,catalog,catalog_full_text/title/z_related_career_skill</key> + <key>description | catalog_full_text/description/z_related_uid</key> + <key>parent_description | catalog_full_text/description/z_related_parent</key> + <key>parent_title | catalog_full_text/title/z_related_parent</key> + <key>stock_explanation_title | catalog_full_text/title/z_related_explanation_from_stock</key> + <key>stock_mirror_section_title | catalog_full_text/title/z_related_mirror_section_uid_from_stock</key> + <key>stock_node_title | catalog_full_text/title/z_related_node_uid_from_stock</key> + <key>title | catalog_full_text/title/z_related_uid</key> +</key_list> \ No newline at end of file diff --git a/bt5/erp5_full_text_mroonga_catalog/CatalogResultTableTemplateItem/result_table_list.xml b/bt5/erp5_full_text_mroonga_catalog/CatalogResultTableTemplateItem/result_table_list.xml index 99624bbbc6..685b76687c 100644 --- a/bt5/erp5_full_text_mroonga_catalog/CatalogResultTableTemplateItem/result_table_list.xml +++ b/bt5/erp5_full_text_mroonga_catalog/CatalogResultTableTemplateItem/result_table_list.xml @@ -1,3 +1,4 @@ <key_list> + <key>catalog_full_text</key> <key>full_text</key> </key_list> \ No newline at end of file diff --git a/bt5/erp5_full_text_mroonga_catalog/CatalogSearchKeyTemplateItem/search_key_list.xml b/bt5/erp5_full_text_mroonga_catalog/CatalogSearchKeyTemplateItem/search_key_list.xml new file mode 100644 index 0000000000..caead947b5 --- /dev/null +++ b/bt5/erp5_full_text_mroonga_catalog/CatalogSearchKeyTemplateItem/search_key_list.xml @@ -0,0 +1,8 @@ +<key_list> + <key>SearchableText | MroongaBooleanFullTextKey</key> + <key>catalog_full_text.description | MroongaBooleanFullTextKey</key> + <key>catalog_full_text.title | MroongaBooleanFullTextKey</key> + <key>description | MroongaBooleanFullTextKey</key> + <key>full_text.SearchableText | MroongaBooleanFullTextKey</key> + <key>title | MroongaBooleanFullTextKey</key> +</key_list> \ No newline at end of file diff --git a/bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_full_text_key_list b/bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_full_text_key_list deleted file mode 100644 index 5e90fc7ee3..0000000000 --- a/bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_full_text_key_list +++ /dev/null @@ -1,2 +0,0 @@ -SearchableText -full_text.SearchableText \ No newline at end of file diff --git a/bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_method_id_list b/bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_method_id_list index 20156621a9..e7edc065c8 100644 --- a/bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_method_id_list +++ b/bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_method_id_list @@ -1,9 +1,13 @@ erp5_mysql_innodb/SQLCatalog_deferFullTextIndex erp5_mysql_innodb/SQLCatalog_deferFullTextIndexActivity erp5_mysql_innodb/SQLCatalog_makeFullTextQuery +erp5_mysql_innodb/z0_drop_catalog_fulltext erp5_mysql_innodb/z0_drop_content_translation erp5_mysql_innodb/z0_drop_fulltext +erp5_mysql_innodb/z0_uncatalog_catalog_fulltext erp5_mysql_innodb/z0_uncatalog_fulltext +erp5_mysql_innodb/z_catalog_catalog_fulltext_list erp5_mysql_innodb/z_catalog_fulltext_list +erp5_mysql_innodb/z_create_catalog_fulltext erp5_mysql_innodb/z_create_content_translation erp5_mysql_innodb/z_create_fulltext \ No newline at end of file diff --git a/bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_related_key_list b/bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_related_key_list new file mode 100644 index 0000000000..693452ae6b --- /dev/null +++ b/bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_related_key_list @@ -0,0 +1,8 @@ +career_skill_title | category,catalog,catalog_full_text/title/z_related_career_skill +description | catalog_full_text/description/z_related_uid +parent_description | catalog_full_text/description/z_related_parent +parent_title | catalog_full_text/title/z_related_parent +stock_explanation_title | catalog_full_text/title/z_related_explanation_from_stock +stock_mirror_section_title | catalog_full_text/title/z_related_mirror_section_uid_from_stock +stock_node_title | catalog_full_text/title/z_related_node_uid_from_stock +title | catalog_full_text/title/z_related_uid \ No newline at end of file diff --git a/bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_result_table_list b/bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_result_table_list index 37adfa26ab..0f5a728af0 100644 --- a/bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_result_table_list +++ b/bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_result_table_list @@ -1 +1,2 @@ +catalog_full_text full_text \ No newline at end of file diff --git a/bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_search_key_list b/bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_search_key_list new file mode 100644 index 0000000000..3c63ebce67 --- /dev/null +++ b/bt5/erp5_full_text_mroonga_catalog/bt/template_catalog_search_key_list @@ -0,0 +1,6 @@ +SearchableText | MroongaBooleanFullTextKey +catalog_full_text.description | MroongaBooleanFullTextKey +catalog_full_text.title | MroongaBooleanFullTextKey +description | MroongaBooleanFullTextKey +full_text.SearchableText | MroongaBooleanFullTextKey +title | MroongaBooleanFullTextKey \ No newline at end of file diff --git a/bt5/erp5_full_text_myisam_catalog/CatalogFullTextKeyTemplateItem/full_text_key_list.xml b/bt5/erp5_full_text_myisam_catalog/CatalogFullTextKeyTemplateItem/full_text_key_list.xml index 662e00e9f7..6bee43e19e 100644 --- a/bt5/erp5_full_text_myisam_catalog/CatalogFullTextKeyTemplateItem/full_text_key_list.xml +++ b/bt5/erp5_full_text_myisam_catalog/CatalogFullTextKeyTemplateItem/full_text_key_list.xml @@ -1,4 +1,8 @@ <key_list> <key>SearchableText</key> - <key>full_text.SearchableText</key> + <key>catalog_full_text.description</key> + <key>catalog_full_text.title</key> | + <key>description</key> | + <key>full_text.SearchableText</key> | + <key>title</key> | </key_list> \ No newline at end of file diff --git a/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_deferFullTextIndexActivity.xml b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_deferFullTextIndexActivity.xml index 99f8fa0c33..38959380dd 100644 --- a/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_deferFullTextIndexActivity.xml +++ b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_deferFullTextIndexActivity.xml @@ -68,8 +68,9 @@ for path in path_list:\n try:\n tmp_dict = {}\n for property in property_list:\n - if property == \'SearchableText\':\n - value = obj.SearchableText()\n + getter = getattr(obj, property, None)\n + if getter is not None and callable(getter):\n + value = getter()\n else:\n value = getattr(obj, \'get%s\' % UpperCase(property))()\n tmp_dict[property] = value\n diff --git a/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_catalog_fulltext.catalog_keys.xml b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_catalog_fulltext.catalog_keys.xml new file mode 100644 index 0000000000..b0fe64af00 --- /dev/null +++ b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_catalog_fulltext.catalog_keys.xml @@ -0,0 +1,5 @@ +<catalog_method> + <item key="sql_clear_catalog" type="int"> + <value>1</value> + </item> +</catalog_method> diff --git a/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_catalog_fulltext.xml b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_catalog_fulltext.xml new file mode 100644 index 0000000000..d9dc3890ee --- /dev/null +++ b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_catalog_fulltext.xml @@ -0,0 +1,70 @@ +<?xml version="1.0"?> +<ZopeData> + <record id="1" aka="AAAAAAAAAAE="> + <pickle> + <global name="SQL" module="Products.ZSQLMethods.SQL"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>_col</string> </key> + <value> + <tuple/> + </value> + </item> + <item> + <key> <string>allow_simple_one_argument_traversal</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>arguments_src</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>cache_time_</string> </key> + <value> <int>0</int> </value> + </item> + <item> + <key> <string>class_file_</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>class_name_</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>connection_hook</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>connection_id</string> </key> + <value> <string>erp5_sql_connection</string> </value> + </item> + <item> + <key> <string>id</string> </key> + <value> <string>z0_drop_catalog_fulltext</string> </value> + </item> + <item> + <key> <string>max_cache_</string> </key> + <value> <int>100</int> </value> + </item> + <item> + <key> <string>max_rows_</string> </key> + <value> <int>1000</int> </value> + </item> + <item> + <key> <string>src</string> </key> + <value> <string>DROP TABLE IF EXISTS catalog_full_text</string> </value> + </item> + <item> + <key> <string>title</string> </key> + <value> <string></string> </value> + </item> + </dictionary> + </pickle> + </record> +</ZopeData> diff --git a/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_catalog_fulltext.catalog_keys.xml b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_catalog_fulltext.catalog_keys.xml new file mode 100644 index 0000000000..d29d36d9f0 --- /dev/null +++ b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_catalog_fulltext.catalog_keys.xml @@ -0,0 +1,5 @@ +<catalog_method> + <item key="sql_uncatalog_object" type="int"> + <value>1</value> + </item> +</catalog_method> diff --git a/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_catalog_fulltext.xml b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_catalog_fulltext.xml new file mode 100644 index 0000000000..d9493f4955 --- /dev/null +++ b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_catalog_fulltext.xml @@ -0,0 +1,68 @@ +<?xml version="1.0"?> +<ZopeData> + <record id="1" aka="AAAAAAAAAAE="> + <pickle> + <global name="SQL" module="Products.ZSQLMethods.SQL"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>allow_simple_one_argument_traversal</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>arguments_src</string> </key> + <value> <string>uid</string> </value> + </item> + <item> + <key> <string>cache_time_</string> </key> + <value> <int>0</int> </value> + </item> + <item> + <key> <string>class_file_</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>class_name_</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>connection_hook</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>connection_id</string> </key> + <value> <string>erp5_sql_deferred_connection</string> </value> + </item> + <item> + <key> <string>id</string> </key> + <value> <string>z0_uncatalog_catalog_fulltext</string> </value> + </item> + <item> + <key> <string>max_cache_</string> </key> + <value> <int>100</int> </value> + </item> + <item> + <key> <string>max_rows_</string> </key> + <value> <int>1000</int> </value> + </item> + <item> + <key> <string>src</string> </key> + <value> <string encoding="cdata"><![CDATA[ + +DELETE FROM catalog_full_text WHERE <dtml-sqltest uid op=eq type=int> + +]]></string> </value> + </item> + <item> + <key> <string>title</string> </key> + <value> <string></string> </value> + </item> + </dictionary> + </pickle> + </record> +</ZopeData> diff --git a/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_catalog_fulltext_list.catalog_keys.xml b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_catalog_fulltext_list.catalog_keys.xml new file mode 100644 index 0000000000..c95a68655e --- /dev/null +++ b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_catalog_fulltext_list.catalog_keys.xml @@ -0,0 +1,5 @@ +<catalog_method> + <item key="sql_catalog_object_list" type="int"> + <value>1</value> + </item> +</catalog_method> diff --git a/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_catalog_fulltext_list.xml b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_catalog_fulltext_list.xml new file mode 100644 index 0000000000..06e374fa75 --- /dev/null +++ b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_catalog_fulltext_list.xml @@ -0,0 +1,80 @@ +<?xml version="1.0"?> +<ZopeData> + <record id="1" aka="AAAAAAAAAAE="> + <pickle> + <global name="SQL" module="Products.ZSQLMethods.SQL"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>allow_simple_one_argument_traversal</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>arguments_src</string> </key> + <value> <string>uid\r\n +getTitle\r\n +getDescription</string> </value> + </item> + <item> + <key> <string>cache_time_</string> </key> + <value> <int>0</int> </value> + </item> + <item> + <key> <string>class_file_</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>class_name_</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>connection_hook</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>connection_id</string> </key> + <value> <string>erp5_sql_deferred_connection</string> </value> + </item> + <item> + <key> <string>id</string> </key> + <value> <string>z_catalog_catalog_fulltext_list</string> </value> + </item> + <item> + <key> <string>max_cache_</string> </key> + <value> <int>100</int> </value> + </item> + <item> + <key> <string>max_rows_</string> </key> + <value> <int>1000</int> </value> + </item> + <item> + <key> <string>src</string> </key> + <value> <string encoding="cdata"><![CDATA[ + +REPLACE INTO\n + catalog_full_text (`uid`, `title`, `description`)\n +VALUES\n +<dtml-in prefix="loop" expr="_.range(_.len(uid))">\n +(\n + <dtml-sqlvar expr="uid[loop_item]" type="int">, \n + <dtml-sqlvar expr="getTitle[loop_item]" type="string" optional>,\n + <dtml-sqlvar expr="getDescription[loop_item]" type="string" optional>\n +)<dtml-unless sequence-end>,</dtml-unless>\n +</dtml-in>\n + + +]]></string> </value> + </item> + <item> + <key> <string>title</string> </key> + <value> <string></string> </value> + </item> + </dictionary> + </pickle> + </record> +</ZopeData> diff --git a/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_fulltext_list.xml b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_fulltext_list.xml index fb0ecee42f..1f0e6f1e03 100644 --- a/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_fulltext_list.xml +++ b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_fulltext_list.xml @@ -55,21 +55,16 @@ SearchableText</string> </value> <key> <string>src</string> </key> <value> <string encoding="cdata"><![CDATA[ -DELETE FROM\n - full_text\n -WHERE\n -<dtml-in uid>\n - uid=<dtml-sqlvar sequence-item type="int"><dtml-if sequence-end><dtml-else> OR </dtml-if>\n -</dtml-in>\n -;\n -<dtml-var "\'\\0\'"><dtml-let document_list="[]">\n +<dtml-let document_list="[]" delete_list="[]">\n <dtml-in prefix="loop" expr="_.range(_.len(uid))">\n <dtml-if "SearchableText[loop_item]">\n <dtml-call expr="document_list.append(loop_item)">\n + <dtml-else>\n + <dtml-call expr="delete_list.append(loop_item)">\n </dtml-if>\n </dtml-in>\n <dtml-if expr="_.len(document_list) > 0">\n -INSERT INTO\n +REPLACE INTO\n full_text\n VALUES\n <dtml-in prefix="loop" expr="document_list">\n @@ -79,7 +74,19 @@ VALUES\n )<dtml-unless sequence-end>,</dtml-unless>\n </dtml-in>\n </dtml-if>\n -</dtml-let> + <dtml-if expr="_.len(delete_list) > 0">\n +<dtml-var sql_delimiter>\n +DELETE FROM\n + full_text\n +WHERE uid IN\n +( \n + <dtml-in prefix="loop" expr="delete_list">\n + <dtml-sqlvar expr="uid[loop_item]" type="int"><dtml-unless sequence-end>,</dtml-unless>\n + </dtml-in>\n +)\n + </dtml-if>\n +</dtml-let>\n + ]]></string> </value> </item> diff --git a/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_catalog_fulltext.catalog_keys.xml b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_catalog_fulltext.catalog_keys.xml new file mode 100644 index 0000000000..b0fe64af00 --- /dev/null +++ b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_catalog_fulltext.catalog_keys.xml @@ -0,0 +1,5 @@ +<catalog_method> + <item key="sql_clear_catalog" type="int"> + <value>1</value> + </item> +</catalog_method> diff --git a/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_catalog_fulltext.xml b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_catalog_fulltext.xml new file mode 100644 index 0000000000..ce9ad33f91 --- /dev/null +++ b/bt5/erp5_full_text_myisam_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_catalog_fulltext.xml @@ -0,0 +1,82 @@ +<?xml version="1.0"?> +<ZopeData> + <record id="1" aka="AAAAAAAAAAE="> + <pickle> + <global name="SQL" module="Products.ZSQLMethods.SQL"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>_col</string> </key> + <value> + <tuple/> + </value> + </item> + <item> + <key> <string>allow_simple_one_argument_traversal</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>arguments_src</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>cache_time_</string> </key> + <value> <int>0</int> </value> + </item> + <item> + <key> <string>class_file_</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>class_name_</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>connection_hook</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>connection_id</string> </key> + <value> <string>erp5_sql_connection</string> </value> + </item> + <item> + <key> <string>id</string> </key> + <value> <string>z_create_catalog_fulltext</string> </value> + </item> + <item> + <key> <string>max_cache_</string> </key> + <value> <int>100</int> </value> + </item> + <item> + <key> <string>max_rows_</string> </key> + <value> <int>1000</int> </value> + </item> + <item> + <key> <string>src</string> </key> + <value> <string># Host:\n +# Database: test\n +# Table: \'catalog_full_text\'\n +#\n +CREATE TABLE `catalog_full_text` (\n + `uid` BIGINT UNSIGNED NOT NULL,\n + `title` varchar(255) default \'\',\n + `description` text,\n + PRIMARY KEY (`uid`),\n + FULLTEXT `title` (`title`),\n + FULLTEXT `description` (`description`)\n +) ENGINE=MyISAM;\n +</string> </value> + </item> + <item> + <key> <string>title</string> </key> + <value> <string></string> </value> + </item> + </dictionary> + </pickle> + </record> +</ZopeData> diff --git a/bt5/erp5_full_text_myisam_catalog/CatalogRelatedKeyTemplateItem/related_key_list.xml b/bt5/erp5_full_text_myisam_catalog/CatalogRelatedKeyTemplateItem/related_key_list.xml new file mode 100644 index 0000000000..2ced6f2d72 --- /dev/null +++ b/bt5/erp5_full_text_myisam_catalog/CatalogRelatedKeyTemplateItem/related_key_list.xml @@ -0,0 +1,10 @@ +<key_list> + <key>career_skill_title | category,catalog,catalog_full_text/title/z_related_career_skill</key> + <key>description | catalog_full_text/description/z_related_uid</key> + <key>parent_description | catalog_full_text/description/z_related_parent</key> + <key>parent_title | catalog_full_text/title/z_related_parent</key> + <key>stock_explanation_title | catalog_full_text/title/z_related_explanation_from_stock</key> + <key>stock_mirror_section_title | catalog_full_text/title/z_related_mirror_section_uid_from_stock</key> + <key>stock_node_title | catalog_full_text/title/z_related_node_uid_from_stock</key> + <key>title | catalog_full_text/title/z_related_uid</key> +</key_list> \ No newline at end of file diff --git a/bt5/erp5_full_text_myisam_catalog/CatalogResultTableTemplateItem/result_table_list.xml b/bt5/erp5_full_text_myisam_catalog/CatalogResultTableTemplateItem/result_table_list.xml index 99624bbbc6..685b76687c 100644 --- a/bt5/erp5_full_text_myisam_catalog/CatalogResultTableTemplateItem/result_table_list.xml +++ b/bt5/erp5_full_text_myisam_catalog/CatalogResultTableTemplateItem/result_table_list.xml @@ -1,3 +1,4 @@ <key_list> + <key>catalog_full_text</key> <key>full_text</key> </key_list> \ No newline at end of file diff --git a/bt5/erp5_full_text_myisam_catalog/bt/template_catalog_full_text_key_list b/bt5/erp5_full_text_myisam_catalog/bt/template_catalog_full_text_key_list index 5e90fc7ee3..163cb04a95 100644 --- a/bt5/erp5_full_text_myisam_catalog/bt/template_catalog_full_text_key_list +++ b/bt5/erp5_full_text_myisam_catalog/bt/template_catalog_full_text_key_list @@ -1,2 +1,6 @@ SearchableText -full_text.SearchableText \ No newline at end of file +catalog_full_text.description +catalog_full_text.title +description +full_text.SearchableText +title \ No newline at end of file diff --git a/bt5/erp5_full_text_myisam_catalog/bt/template_catalog_method_id_list b/bt5/erp5_full_text_myisam_catalog/bt/template_catalog_method_id_list index 20156621a9..e7edc065c8 100644 --- a/bt5/erp5_full_text_myisam_catalog/bt/template_catalog_method_id_list +++ b/bt5/erp5_full_text_myisam_catalog/bt/template_catalog_method_id_list @@ -1,9 +1,13 @@ erp5_mysql_innodb/SQLCatalog_deferFullTextIndex erp5_mysql_innodb/SQLCatalog_deferFullTextIndexActivity erp5_mysql_innodb/SQLCatalog_makeFullTextQuery +erp5_mysql_innodb/z0_drop_catalog_fulltext erp5_mysql_innodb/z0_drop_content_translation erp5_mysql_innodb/z0_drop_fulltext +erp5_mysql_innodb/z0_uncatalog_catalog_fulltext erp5_mysql_innodb/z0_uncatalog_fulltext +erp5_mysql_innodb/z_catalog_catalog_fulltext_list erp5_mysql_innodb/z_catalog_fulltext_list +erp5_mysql_innodb/z_create_catalog_fulltext erp5_mysql_innodb/z_create_content_translation erp5_mysql_innodb/z_create_fulltext \ No newline at end of file diff --git a/bt5/erp5_full_text_myisam_catalog/bt/template_catalog_related_key_list b/bt5/erp5_full_text_myisam_catalog/bt/template_catalog_related_key_list new file mode 100644 index 0000000000..693452ae6b --- /dev/null +++ b/bt5/erp5_full_text_myisam_catalog/bt/template_catalog_related_key_list @@ -0,0 +1,8 @@ +career_skill_title | category,catalog,catalog_full_text/title/z_related_career_skill +description | catalog_full_text/description/z_related_uid +parent_description | catalog_full_text/description/z_related_parent +parent_title | catalog_full_text/title/z_related_parent +stock_explanation_title | catalog_full_text/title/z_related_explanation_from_stock +stock_mirror_section_title | catalog_full_text/title/z_related_mirror_section_uid_from_stock +stock_node_title | catalog_full_text/title/z_related_node_uid_from_stock +title | catalog_full_text/title/z_related_uid \ No newline at end of file diff --git a/bt5/erp5_full_text_myisam_catalog/bt/template_catalog_result_table_list b/bt5/erp5_full_text_myisam_catalog/bt/template_catalog_result_table_list index 37adfa26ab..0f5a728af0 100644 --- a/bt5/erp5_full_text_myisam_catalog/bt/template_catalog_result_table_list +++ b/bt5/erp5_full_text_myisam_catalog/bt/template_catalog_result_table_list @@ -1 +1,2 @@ +catalog_full_text full_text \ No newline at end of file diff --git a/bt5/erp5_ingestion/bt/test_dependency_list b/bt5/erp5_ingestion/bt/test_dependency_list index 105482554a..2f97a2f2c2 100644 --- a/bt5/erp5_ingestion/bt/test_dependency_list +++ b/bt5/erp5_ingestion/bt/test_dependency_list @@ -1,4 +1,4 @@ -erp5_full_text_myisam_catalog +erp5_full_text_mroonga_catalog erp5_ingestion_mysql_innodb_catalog erp5_web erp5_crm diff --git a/bt5/erp5_item/CatalogRelatedKeyTemplateItem/related_key_list.xml b/bt5/erp5_item/CatalogRelatedKeyTemplateItem/related_key_list.xml index e34497d8c0..4c324fb3d7 100644 --- a/bt5/erp5_item/CatalogRelatedKeyTemplateItem/related_key_list.xml +++ b/bt5/erp5_item/CatalogRelatedKeyTemplateItem/related_key_list.xml @@ -1,6 +1,6 @@ <key_list> <key>item_catalog_portal_type | catalog/portal_type/z_related_item_catalog</key> <key>item_catalog_reference | catalog/reference/z_related_item_catalog</key> - <key>item_catalog_title | catalog/title/z_related_item_catalog</key> + <key>item_catalog_title | catalog_full_text/title/z_related_item_catalog</key> <key>item_catalog_validation_state | catalog/validation_state/z_related_item_catalog</key> </key_list> \ No newline at end of file diff --git a/bt5/erp5_item/bt/template_catalog_related_key_list b/bt5/erp5_item/bt/template_catalog_related_key_list index eecc7c1038..0057439296 100644 --- a/bt5/erp5_item/bt/template_catalog_related_key_list +++ b/bt5/erp5_item/bt/template_catalog_related_key_list @@ -1,4 +1,4 @@ -item_catalog_title | catalog/title/z_related_item_catalog +item_catalog_title | catalog_full_text/title/z_related_item_catalog item_catalog_portal_type | catalog/portal_type/z_related_item_catalog item_catalog_reference | catalog/reference/z_related_item_catalog item_catalog_validation_state | catalog/validation_state/z_related_item_catalog \ No newline at end of file diff --git a/bt5/erp5_km_ui_test/PathTemplateItem/portal_tests/erp5_km_zuite/testTopSearchBoxClicking.xml b/bt5/erp5_km_ui_test/PathTemplateItem/portal_tests/erp5_km_zuite/testTopSearchBoxClicking.xml index ecfe64f3c1..4e2e984d63 100644 --- a/bt5/erp5_km_ui_test/PathTemplateItem/portal_tests/erp5_km_zuite/testTopSearchBoxClicking.xml +++ b/bt5/erp5_km_ui_test/PathTemplateItem/portal_tests/erp5_km_zuite/testTopSearchBoxClicking.xml @@ -96,7 +96,7 @@ <tr>\n <td>type</td>\n <td>search_text</td>\n - <td>Pouet_NO_EXISTS</td>\n + <td>Poueet</td>\n </tr>\n <tr>\n <td>clickAndWait</td>\n @@ -111,7 +111,7 @@ <tr>\n <td>verifyValue</td>\n <td>search_text</td>\n - <td>Pouet_NO_EXISTS</td>\n + <td>Poueet</td>\n </tr>\n <tr>\n <td>type</td>\n diff --git a/bt5/erp5_paypal_secure_payment/bt/test_dependency_list b/bt5/erp5_paypal_secure_payment/bt/test_dependency_list index 418a1a563a..bff77e32d8 100644 --- a/bt5/erp5_paypal_secure_payment/bt/test_dependency_list +++ b/bt5/erp5_paypal_secure_payment/bt/test_dependency_list @@ -1 +1 @@ -erp5_full_text_myisam_catalog \ No newline at end of file +erp5_full_text_mroonga_catalog \ No newline at end of file diff --git a/bt5/erp5_payzen_secure_payment/bt/test_dependency_list b/bt5/erp5_payzen_secure_payment/bt/test_dependency_list index 418a1a563a..bff77e32d8 100644 --- a/bt5/erp5_payzen_secure_payment/bt/test_dependency_list +++ b/bt5/erp5_payzen_secure_payment/bt/test_dependency_list @@ -1 +1 @@ -erp5_full_text_myisam_catalog \ No newline at end of file +erp5_full_text_mroonga_catalog \ No newline at end of file diff --git a/bt5/erp5_pdf_merge/bt/test_dependency_list b/bt5/erp5_pdf_merge/bt/test_dependency_list index 117dc3e54f..bc72f3a1b7 100644 --- a/bt5/erp5_pdf_merge/bt/test_dependency_list +++ b/bt5/erp5_pdf_merge/bt/test_dependency_list @@ -1,4 +1,4 @@ -erp5_full_text_myisam_catalog +erp5_full_text_mroonga_catalog erp5_base erp5_web erp5_ingestion diff --git a/bt5/erp5_research_item/bt/test_dependency_list b/bt5/erp5_research_item/bt/test_dependency_list index 72f980091a..ff050e6eaa 100644 --- a/bt5/erp5_research_item/bt/test_dependency_list +++ b/bt5/erp5_research_item/bt/test_dependency_list @@ -1,4 +1,4 @@ -erp5_full_text_myisam_catalog +erp5_full_text_mroonga_catalog erp5_simulation erp5_configurator_standard_trade_template erp5_simulation_test diff --git a/bt5/erp5_safeimage/bt/test_dependency_list b/bt5/erp5_safeimage/bt/test_dependency_list index 73ffa2a14b..665e8c44c9 100644 --- a/bt5/erp5_safeimage/bt/test_dependency_list +++ b/bt5/erp5_safeimage/bt/test_dependency_list @@ -1,3 +1,3 @@ -erp5_full_text_myisam_catalog +erp5_full_text_mroonga_catalog erp5_ingestion_mysql_innodb_catalog erp5_ingestion \ No newline at end of file diff --git a/bt5/erp5_social_contracts/bt/test_dependency_list b/bt5/erp5_social_contracts/bt/test_dependency_list index 418a1a563a..bff77e32d8 100644 --- a/bt5/erp5_social_contracts/bt/test_dependency_list +++ b/bt5/erp5_social_contracts/bt/test_dependency_list @@ -1 +1 @@ -erp5_full_text_myisam_catalog \ No newline at end of file +erp5_full_text_mroonga_catalog \ No newline at end of file diff --git a/bt5/erp5_syncml_test_data/bt/test_dependency_list b/bt5/erp5_syncml_test_data/bt/test_dependency_list index 418a1a563a..bff77e32d8 100644 --- a/bt5/erp5_syncml_test_data/bt/test_dependency_list +++ b/bt5/erp5_syncml_test_data/bt/test_dependency_list @@ -1 +1 @@ -erp5_full_text_myisam_catalog \ No newline at end of file +erp5_full_text_mroonga_catalog \ No newline at end of file diff --git a/bt5/erp5_test_result/DocumentTemplateItem/portal_components/document.erp5.ERP5ScalabilityDistributor.py b/bt5/erp5_test_result/DocumentTemplateItem/portal_components/document.erp5.ERP5ScalabilityDistributor.py index c68f2c010f..34e048f0cb 100644 --- a/bt5/erp5_test_result/DocumentTemplateItem/portal_components/document.erp5.ERP5ScalabilityDistributor.py +++ b/bt5/erp5_test_result/DocumentTemplateItem/portal_components/document.erp5.ERP5ScalabilityDistributor.py @@ -26,6 +26,7 @@ ############################################################################## from Products.ERP5.Document.ERP5ProjectUnitTestDistributor import ERP5ProjectUnitTestDistributor +from Products.ZSQLCatalog.SQLCatalog import SimpleQuery from zLOG import LOG,ERROR from AccessControl import ClassSecurityInfo @@ -110,7 +111,10 @@ class ERP5ScalabilityDistributor(ERP5ProjectUnitTestDistributor): tag = "%s_%s" % (self.getRelativeUrl(), title) if portal.portal_activities.countMessageWithTag(tag) == 0: - test_node_list = test_node_module.searchFolder(portal_type="Test Node",title=title) + test_node_list = test_node_module.searchFolder( + portal_type="Test Node", + title=SimpleQuery(comparison_operator='=', title=title), + ) assert len(test_node_list) in (0, 1), "Unable to find testnode : %s" % title test_node = None if len(test_node_list) == 1: @@ -129,7 +133,8 @@ class ERP5ScalabilityDistributor(ERP5ProjectUnitTestDistributor): isMasterTestnode : return True if the node given in parameter exists and is a validated master """ test_node_module = self._getTestNodeModule() - test_node_master = [ node for node in test_node_module.searchFolder(portal_type="Test Node", title=title, + test_node_master = [ node for node in test_node_module.searchFolder(portal_type="Test Node", + title=SimpleQuery(comparison_operator='=', title=title), specialise_uid=self.getUid(), validation_state="validated") if node.getMaster() == 1 ] if len(test_node_master) == 1: diff --git a/bt5/erp5_test_result/bt/test_dependency_list b/bt5/erp5_test_result/bt/test_dependency_list index 9a77167a96..8149202de5 100644 --- a/bt5/erp5_test_result/bt/test_dependency_list +++ b/bt5/erp5_test_result/bt/test_dependency_list @@ -1,2 +1,2 @@ -erp5_full_text_myisam_catalog +erp5_full_text_mroonga_catalog erp5_base \ No newline at end of file diff --git a/bt5/erp5_tiosafe_oxatis_test/TestTemplateItem/testOxatisSynchronization.py b/bt5/erp5_tiosafe_oxatis_test/TestTemplateItem/testOxatisSynchronization.py index a115c892fd..3ec187b2d7 100644 --- a/bt5/erp5_tiosafe_oxatis_test/TestTemplateItem/testOxatisSynchronization.py +++ b/bt5/erp5_tiosafe_oxatis_test/TestTemplateItem/testOxatisSynchronization.py @@ -41,7 +41,7 @@ class TestOxatisSynchronization(ERP5TypeTestCase): """ Return the list of BT required by unit tests. """ return ( 'erp5_core_proxy_field_legacy', - 'erp5_full_text_myisam_catalog', + 'erp5_full_text_mroonga_catalog', 'erp5_base', 'erp5_pdm', 'erp5_simulation', diff --git a/bt5/erp5_ui_test/PathTemplateItem/portal_tests/relation_field_zuite/testMultiRelationFieldSearchDialogChangePage.xml b/bt5/erp5_ui_test/PathTemplateItem/portal_tests/relation_field_zuite/testMultiRelationFieldSearchDialogChangePage.xml index 043e0280ef..cd2aa03273 100644 --- a/bt5/erp5_ui_test/PathTemplateItem/portal_tests/relation_field_zuite/testMultiRelationFieldSearchDialogChangePage.xml +++ b/bt5/erp5_ui_test/PathTemplateItem/portal_tests/relation_field_zuite/testMultiRelationFieldSearchDialogChangePage.xml @@ -102,7 +102,7 @@ <tr>\n <td>assertValue</td>\n <td>listbox_title</td>\n - <td>"%1%" OR "%2%"</td>\n + <td>("%1%" OR "%2%")</td>\n </tr>\n <tr>\n <td>clickAndWait</td>\n @@ -119,7 +119,7 @@ <tr>\n <td>assertValue</td>\n <td>listbox_title</td>\n - <td>"%1%" OR "%2%"</td>\n + <td>("%1%" OR "%2%")</td>\n </tr>\n \n <tr>\n @@ -137,7 +137,7 @@ <tr>\n <td>assertValue</td>\n <td>listbox_title</td>\n - <td>"%1%" OR "%2%"</td>\n + <td>("%1%" OR "%2%")</td>\n </tr>\n \n <tr>\n @@ -181,7 +181,7 @@ <tr>\n <td>assertValue</td>\n <td>listbox_title</td>\n - <td>"%1%" OR "%2%"</td>\n + <td>("%1%" OR "%2%")</td>\n </tr>\n \n <tal:block tal:condition="python: context.TestTool_getSkinName()!=\'Mobile\'">\n @@ -213,7 +213,7 @@ <tr>\n <td>assertValue</td>\n <td>listbox_title</td>\n - <td>"%1%" OR "%2%"</td>\n + <td>("%1%" OR "%2%")</td>\n </tr>\n \n <tr>\n diff --git a/bt5/erp5_ui_test/PathTemplateItem/portal_tests/relation_field_zuite/testSimpleRelationFieldWithListbox.xml b/bt5/erp5_ui_test/PathTemplateItem/portal_tests/relation_field_zuite/testSimpleRelationFieldWithListbox.xml index 97a0450b98..2f9cc69494 100644 --- a/bt5/erp5_ui_test/PathTemplateItem/portal_tests/relation_field_zuite/testSimpleRelationFieldWithListbox.xml +++ b/bt5/erp5_ui_test/PathTemplateItem/portal_tests/relation_field_zuite/testSimpleRelationFieldWithListbox.xml @@ -78,7 +78,7 @@ <tr>\n <td>type</td>\n <td>field_my_foo_category_title</td>\n - <td>b</td>\n + <td>=b</td>\n </tr>\n <tr>\n <td>type</td>\n diff --git a/bt5/erp5_ui_test/PathTemplateItem/portal_tests/relation_field_zuite/testSimpleRequiredRelationField.xml b/bt5/erp5_ui_test/PathTemplateItem/portal_tests/relation_field_zuite/testSimpleRequiredRelationField.xml index 758b44a191..af43c7f6d7 100644 --- a/bt5/erp5_ui_test/PathTemplateItem/portal_tests/relation_field_zuite/testSimpleRequiredRelationField.xml +++ b/bt5/erp5_ui_test/PathTemplateItem/portal_tests/relation_field_zuite/testSimpleRequiredRelationField.xml @@ -126,7 +126,7 @@ metal:use-macro="here/RelationFieldZuite_CommonTemplate/macros/init"\n <tr>\n <td>type</td>\n <td>listbox_title</td>\n - <td>a</td>\n + <td>=a</td>\n </tr>\n <tr>\n <td>clickAndWait</td>\n @@ -135,7 +135,7 @@ metal:use-macro="here/RelationFieldZuite_CommonTemplate/macros/init"\n </tr>\n <tr>\n <td>click</td>\n - <td>//*[@class=\'listbox-data-line-0 DataA\']//input[@type="checkbox"]</td>\n + <td>//tr//a[.="a"]/parent::td/preceding-sibling::td/input[@type="checkbox"]</td>\n <td></td>\n </tr>\n <tr>\n diff --git a/bt5/erp5_upgrader/bt/test_dependency_list b/bt5/erp5_upgrader/bt/test_dependency_list index 576e46274b..eb1f0199f1 100644 --- a/bt5/erp5_upgrader/bt/test_dependency_list +++ b/bt5/erp5_upgrader/bt/test_dependency_list @@ -1,3 +1,3 @@ -erp5_full_text_myisam_catalog +erp5_full_text_mroonga_catalog erp5_base erp5_upgrader_test \ No newline at end of file diff --git a/bt5/erp5_upgrader_test/SkinTemplateItem/portal_skins/erp5_upgrader_test/TemplateTool_checkPreUpgradeConsistency.xml b/bt5/erp5_upgrader_test/SkinTemplateItem/portal_skins/erp5_upgrader_test/TemplateTool_checkPreUpgradeConsistency.xml index 306f9b908f..9d2cf99bbb 100644 --- a/bt5/erp5_upgrader_test/SkinTemplateItem/portal_skins/erp5_upgrader_test/TemplateTool_checkPreUpgradeConsistency.xml +++ b/bt5/erp5_upgrader_test/SkinTemplateItem/portal_skins/erp5_upgrader_test/TemplateTool_checkPreUpgradeConsistency.xml @@ -52,7 +52,7 @@ <key> <string>_body</string> </key> <value> <string>template_tool = context\n \n -return template_tool.upgradeSite((\'erp5_full_text_myisam_catalog\',),\n +return template_tool.upgradeSite((\'erp5_full_text_mroonga_catalog\',),\n dry_run=(not fixit))\n </string> </value> </item> diff --git a/bt5/erp5_web_shacache/bt/test_dependency_list b/bt5/erp5_web_shacache/bt/test_dependency_list index 418a1a563a..bff77e32d8 100644 --- a/bt5/erp5_web_shacache/bt/test_dependency_list +++ b/bt5/erp5_web_shacache/bt/test_dependency_list @@ -1 +1 @@ -erp5_full_text_myisam_catalog \ No newline at end of file +erp5_full_text_mroonga_catalog \ No newline at end of file diff --git a/bt5/erp5_web_shadir/bt/test_dependency_list b/bt5/erp5_web_shadir/bt/test_dependency_list index d7bf03237e..6d48b667bc 100644 --- a/bt5/erp5_web_shadir/bt/test_dependency_list +++ b/bt5/erp5_web_shadir/bt/test_dependency_list @@ -1,4 +1,4 @@ -erp5_full_text_myisam_catalog +erp5_full_text_mroonga_catalog erp5_base erp5_jquery erp5_ingestion_mysql_innodb_catalog diff --git a/bt5/erp5_web_ung_core/bt/test_dependency_list b/bt5/erp5_web_ung_core/bt/test_dependency_list index 418a1a563a..bff77e32d8 100644 --- a/bt5/erp5_web_ung_core/bt/test_dependency_list +++ b/bt5/erp5_web_ung_core/bt/test_dependency_list @@ -1 +1 @@ -erp5_full_text_myisam_catalog \ No newline at end of file +erp5_full_text_mroonga_catalog \ No newline at end of file diff --git a/bt5/erp5_web_ung_role/bt/test_dependency_list b/bt5/erp5_web_ung_role/bt/test_dependency_list index fb492e5d53..85d0a05770 100644 --- a/bt5/erp5_web_ung_role/bt/test_dependency_list +++ b/bt5/erp5_web_ung_role/bt/test_dependency_list @@ -1,4 +1,4 @@ -erp5_full_text_myisam_catalog +erp5_full_text_mroonga_catalog erp5_base erp5_web erp5_ingestion_mysql_innodb_catalog diff --git a/bt5/erp5_web_ung_theme/bt/test_dependency_list b/bt5/erp5_web_ung_theme/bt/test_dependency_list index 768ccd338e..bdc5ea937b 100644 --- a/bt5/erp5_web_ung_theme/bt/test_dependency_list +++ b/bt5/erp5_web_ung_theme/bt/test_dependency_list @@ -1,5 +1,5 @@ erp5_ingestion_mysql_innodb_catalog -erp5_full_text_myisam_catalog +erp5_full_text_mroonga_catalog erp5_base erp5_jquery erp5_web diff --git a/bt5/networkcache_erp5/bt/test_dependency_list b/bt5/networkcache_erp5/bt/test_dependency_list index 1dafe8b1e0..eb7f29e9d5 100644 --- a/bt5/networkcache_erp5/bt/test_dependency_list +++ b/bt5/networkcache_erp5/bt/test_dependency_list @@ -1,3 +1,3 @@ -erp5_full_text_myisam_catalog +erp5_full_text_mroonga_catalog erp5_pdm erp5_data_set \ No newline at end of file diff --git a/bt5/test_conflict_resolution/bt/test_dependency_list b/bt5/test_conflict_resolution/bt/test_dependency_list index 418a1a563a..bff77e32d8 100644 --- a/bt5/test_conflict_resolution/bt/test_dependency_list +++ b/bt5/test_conflict_resolution/bt/test_dependency_list @@ -1 +1 @@ -erp5_full_text_myisam_catalog \ No newline at end of file +erp5_full_text_mroonga_catalog \ No newline at end of file diff --git a/product/ERP5/Document/ERP5ProjectUnitTestDistributor.py b/product/ERP5/Document/ERP5ProjectUnitTestDistributor.py index 6f229dfb59..c37b4a8b1b 100644 --- a/product/ERP5/Document/ERP5ProjectUnitTestDistributor.py +++ b/product/ERP5/Document/ERP5ProjectUnitTestDistributor.py @@ -37,7 +37,7 @@ import string from zLOG import LOG,INFO,ERROR from AccessControl import ClassSecurityInfo from Products.ERP5Type import Permissions -from Products.ZSQLCatalog.SQLCatalog import Query +from Products.ZSQLCatalog.SQLCatalog import SimpleQuery TEST_SUITE_MAX = 4 # Depending on the test suite priority, we will affect # more or less cores @@ -210,7 +210,10 @@ class ERP5ProjectUnitTestDistributor(XMLObject): tag = "%s_%s" % (self.getRelativeUrl(), title) if portal.portal_activities.countMessageWithTag(tag) == 0: - test_node_list = test_node_module.searchFolder(portal_type="Test Node",title=title) + test_node_list = test_node_module.searchFolder( + portal_type="Test Node", + title=SimpleQuery(comparison_operator='=', title=title), + ) assert len(test_node_list) in (0, 1), "Unable to find testnode : %s" % title test_node = None if len(test_node_list) == 1: @@ -244,9 +247,11 @@ class ERP5ProjectUnitTestDistributor(XMLObject): from_date = now - 30 def getTestSuiteSortKey(test_suite): test_result = portal.portal_catalog(portal_type="Test Result", - title='="%s"' % test_suite.getTitle(), - modification_date=Query(**{"creation_date": from_date, - "range": "min"}), + title=SimpleQuery(title=test_suite.getTitle()), + creation_date=SimpleQuery( + creation_date=from_date, + comparison_operator='>=', + ), sort_on=[("modification_date", "descending")], limit=1) if len(test_result): @@ -304,7 +309,10 @@ class ERP5ProjectUnitTestDistributor(XMLObject): config_list = [] tag = "%s_%s" % (self.getRelativeUrl(), title) if portal.portal_activities.countMessageWithTag(tag) == 0: - test_node_list = test_node_module.searchFolder(portal_type="Test Node",title=title) + test_node_list = test_node_module.searchFolder( + portal_type="Test Node", + title=SimpleQuery(comparison_operator='=', title=title), + ) assert len(test_node_list) in (0, 1), "Unable to find testnode : %s" % title test_node = None if len(test_node_list) == 1: @@ -365,7 +373,9 @@ class ERP5ProjectUnitTestDistributor(XMLObject): def _getTestNodeFromTitle(self, node_title): test_node_list = self._getTestNodeModule().searchFolder( - portal_type='Test Node', title="='%s'" % node_title) + portal_type="Test Node", + title=SimpleQuery(comparison_operator='=', title=node_title), + ) assert len(test_node_list) == 1, "We found %i test nodes for %s" % ( len(test_node_list), node_title) test_node = test_node_list[0].getObject() @@ -373,7 +383,9 @@ class ERP5ProjectUnitTestDistributor(XMLObject): def _getTestSuiteFromTitle(self, suite_title): test_suite_list = self._getTestSuiteModule().searchFolder( - portal_type='Test Suite', title="='%s'" % suit_tile, validation_state="validated") + portal_type='Test Suite', + title=SimpleQuery(comparison_operator='=', title=suite_title), + validation_state='validated') assert len(test_suite_list) == 1, "We found %i test suite for %s" % ( len(test_suite_list), name) test_suite = test_suite_list[0].getObject() diff --git a/product/ERP5/Tool/TaskDistributionTool.py b/product/ERP5/Tool/TaskDistributionTool.py index edd65d23e5..961e02d9d5 100644 --- a/product/ERP5/Tool/TaskDistributionTool.py +++ b/product/ERP5/Tool/TaskDistributionTool.py @@ -30,6 +30,7 @@ import random from AccessControl import ClassSecurityInfo from Products.ERP5Type import Permissions, PropertySheet, Constraint, interfaces from Products.ERP5Type.Tool.BaseTool import BaseTool +from Products.ZSQLCatalog.SQLCatalog import SimpleQuery from zLOG import LOG from xmlrpclib import Binary @@ -91,7 +92,7 @@ class TaskDistributionTool(BaseTool): def createTestResultLineList(test_result, test_name_list): duration_list = [] previous_test_result_list = portal.test_result_module.searchFolder( - title='="%s"' % test_result.getTitle(), + title=SimpleQuery(comparison_operator='=', title=test_result.getTitle()), sort_on=[('creation_date','descending')], simulation_state=('stopped', 'public_stopped'), limit=1) @@ -126,7 +127,7 @@ class TaskDistributionTool(BaseTool): int_index, reference = revision result_list = portal.test_result_module.searchFolder( portal_type="Test Result", - title='="%s"' % test_title, + title=SimpleQuery(comparison_operator='=', title=test_title), sort_on=(("creation_date","descending"),), limit=1) if result_list: @@ -162,7 +163,7 @@ class TaskDistributionTool(BaseTool): test_result._setIntIndex(int_index) if project_title is not None: project_list = portal.portal_catalog(portal_type='Project', - title='="%s"' % project_title) + title=SimpleQuery(comparison_operator='=', title=project_title)) if len(project_list) != 1: raise ValueError('found this list of project : %r for title %r' % \ ([x.path for x in project_list], project_title)) diff --git a/product/ERP5/bootstrap/erp5_core/bt/test_dependency_list b/product/ERP5/bootstrap/erp5_core/bt/test_dependency_list index 9a77167a96..8149202de5 100644 --- a/product/ERP5/bootstrap/erp5_core/bt/test_dependency_list +++ b/product/ERP5/bootstrap/erp5_core/bt/test_dependency_list @@ -1,2 +1,2 @@ -erp5_full_text_myisam_catalog +erp5_full_text_mroonga_catalog erp5_base \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_makeTranslatedTitleQuery.xml b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_makeTranslatedTitleQuery.xml index 60c0f3ff7f..925c1de5d5 100644 --- a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_makeTranslatedTitleQuery.xml +++ b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_makeTranslatedTitleQuery.xml @@ -56,8 +56,12 @@ portal = context.getPortalObject()\n # This scriptable key supports content_translation if the table is present\n catalog = portal.portal_catalog.getSQLCatalog()\n if \'content_translation\' in catalog.getProperty(\'sql_search_tables\'):\n - return AndQuery(SimpleQuery(**{\'content_translation.translated_text\': value, \'comparison_operator\': \'match\'}),\n - Query(**{\'content_translation.property_name\': \'title\'}))\n + if [x for x in catalog.getProperty(\'sql_catalog_search_keys\', []) if \'Mroonga\' in x]:\n + return AndQuery(SimpleQuery(**{\'content_translation.translated_text\': value, \'comparison_operator\': \'mroonga_boolean\'}),\n + Query(**{\'content_translation.property_name\': \'title\'}))\n + else:\n + return AndQuery(SimpleQuery(**{\'content_translation.translated_text\': value, \'comparison_operator\': \'match_boolean\'}),\n + Query(**{\'content_translation.property_name\': \'title\'}))\n \n # Otherwise it simply use title\n return Query(title=value)\n diff --git a/product/ERP5/tests/testCRM.py b/product/ERP5/tests/testCRM.py index ce0cba0eb2..e716aacddf 100644 --- a/product/ERP5/tests/testCRM.py +++ b/product/ERP5/tests/testCRM.py @@ -82,7 +82,7 @@ class TestCRM(BaseTestCRM): return "CRM" def getBusinessTemplateList(self): - return ('erp5_full_text_myisam_catalog', + return ('erp5_full_text_mroonga_catalog', 'erp5_core_proxy_field_legacy', 'erp5_base', 'erp5_ingestion', @@ -571,7 +571,7 @@ class TestCRMMailIngestion(BaseTestCRM): def getBusinessTemplateList(self): # Mail Ingestion must work with CRM alone. return ('erp5_core_proxy_field_legacy', - 'erp5_full_text_myisam_catalog', + 'erp5_full_text_mroonga_catalog', 'erp5_base', 'erp5_ingestion', 'erp5_ingestion_mysql_innodb_catalog', diff --git a/product/ERP5/tests/testERP5Coordinate.py b/product/ERP5/tests/testERP5Coordinate.py index a847ff78bd..70aa9b8c4c 100644 --- a/product/ERP5/tests/testERP5Coordinate.py +++ b/product/ERP5/tests/testERP5Coordinate.py @@ -48,7 +48,7 @@ class TestERP5Coordinate(ERP5TypeTestCase): Return the list of required business templates. """ return ('erp5_core_proxy_field_legacy', - 'erp5_full_text_myisam_catalog', + 'erp5_full_text_mroonga_catalog', 'erp5_base',) def beforeTearDown(self): diff --git a/product/ERP5/tests/testERP5Credential.py b/product/ERP5/tests/testERP5Credential.py index a7ca271007..872dd082eb 100644 --- a/product/ERP5/tests/testERP5Credential.py +++ b/product/ERP5/tests/testERP5Credential.py @@ -55,7 +55,7 @@ class TestERP5Credential(ERP5TypeTestCase): def getBusinessTemplateList(self): return ( - 'erp5_full_text_myisam_catalog', + 'erp5_full_text_mroonga_catalog', 'erp5_core_proxy_field_legacy', 'erp5_base', 'erp5_jquery', diff --git a/product/ERP5/tests/testERP5eGov.py b/product/ERP5/tests/testERP5eGov.py index 8a48034a5e..9424c682e2 100644 --- a/product/ERP5/tests/testERP5eGov.py +++ b/product/ERP5/tests/testERP5eGov.py @@ -63,7 +63,7 @@ class TestEgov(ERP5TypeTestCase): def getBusinessTemplateList(self): """return list of business templates to be installed. """ bt_list = ['erp5_core_proxy_field_legacy', - 'erp5_full_text_myisam_catalog', + 'erp5_full_text_mroonga_catalog', 'erp5_base', 'erp5_web', 'erp5_ingestion_mysql_innodb_catalog', diff --git a/product/ERP5/tests/testFunctionalRunMyDocSample.py b/product/ERP5/tests/testFunctionalRunMyDocSample.py index 84d3348c4c..84831c2fa0 100644 --- a/product/ERP5/tests/testFunctionalRunMyDocSample.py +++ b/product/ERP5/tests/testFunctionalRunMyDocSample.py @@ -56,7 +56,7 @@ class TestZeleniumRunMyDocSample(ERP5TypeFunctionalTestCase): """ Return the list of business templates. """ - return ('erp5_core_proxy_field_legacy', 'erp5_full_text_myisam_catalog', + return ('erp5_core_proxy_field_legacy', 'erp5_full_text_mroonga_catalog', 'erp5_base', 'erp5_ui_test_core','erp5_web', 'erp5_ingestion', 'erp5_accounting', 'erp5_jquery', 'erp5_dms', 'erp5_jquery_ui', 'erp5_web', diff --git a/product/ERP5/tests/testI18NSearch.py b/product/ERP5/tests/testI18NSearch.py index 930087f35a..f27485fe40 100644 --- a/product/ERP5/tests/testI18NSearch.py +++ b/product/ERP5/tests/testI18NSearch.py @@ -43,21 +43,42 @@ class TestI18NSearch(ERP5TypeTestCase): portal_type='Person', first_name='Gabriel', last_name='Fauré', + description='Quick brown fox jumps over the lazy dog.', ) person2 = person_module.newContent( portal_type='Person', first_name='æ¦è€…å°è·¯', - last_name='実篤' + last_name='実篤', + description='Slow white fox jumps over the diligent dog.', ) self.tic() + # check if 'é' == 'e' collation works result = person_module.searchFolder(SearchableText='Faure') self.assertEqual(len(result), 1) self.assertEqual(result[0].getPath(), person1.getPath()) + result = person_module.searchFolder(title='Faure') + self.assertEqual(len(result), 1) + self.assertEqual(result[0].getPath(), person1.getPath()) + # check if a partial string of CJK string matches result = person_module.searchFolder(SearchableText='æ¦è€…') self.assertEqual(len(result), 1) self.assertEqual(result[0].getPath(), person2.getPath()) + result = person_module.searchFolder(title='æ¦è€…') + self.assertEqual(len(result), 1) + self.assertEqual(result[0].getPath(), person2.getPath()) + + # check boolean language mode search + result = person_module.searchFolder(SearchableText='+quick +fox +dog') + self.assertEqual(len(result), 1) + self.assertEqual(result[0].getPath(), person1.getPath()) + result = person_module.searchFolder(description='+quick +fox +dog') + self.assertEqual(len(result), 1) + self.assertEqual(result[0].getPath(), person1.getPath()) + + # check fulltext search for automatically generated related keys. + self.assertTrue('MATCH' in self.portal.portal_catalog(destination_title='Faure', src__=1)) def test_suite(): suite = unittest.TestSuite() diff --git a/product/ERP5/tests/testKM.py b/product/ERP5/tests/testKM.py index 2669aa310f..e796716f0e 100644 --- a/product/ERP5/tests/testKM.py +++ b/product/ERP5/tests/testKM.py @@ -50,7 +50,7 @@ class TestKMMixIn(TestDocumentMixin): manager_password = '' website_id = 'km_test' business_template_list = ['erp5_core_proxy_field_legacy', - 'erp5_full_text_myisam_catalog','erp5_base', + 'erp5_full_text_mroonga_catalog','erp5_base', 'erp5_jquery', 'erp5_jquery_ui', 'erp5_knowledge_pad', 'erp5_ingestion_mysql_innodb_catalog', 'erp5_ingestion', 'erp5_web', 'erp5_dms', diff --git a/product/ERP5/tests/testSpellChecking.py b/product/ERP5/tests/testSpellChecking.py index 3c67e102ca..68d58633bf 100644 --- a/product/ERP5/tests/testSpellChecking.py +++ b/product/ERP5/tests/testSpellChecking.py @@ -68,7 +68,7 @@ class TestSpellChecking(ERP5TypeTestCase): return "Spell Checking Test" def getBusinessTemplateList(self): - return ('erp5_full_text_myisam_catalog', + return ('erp5_full_text_mroonga_catalog', 'erp5_base', 'erp5_simulation', 'erp5_accounting', diff --git a/product/ERP5/tests/testTemplateTool.py b/product/ERP5/tests/testTemplateTool.py index 01ebb39f81..dc9d6da28c 100644 --- a/product/ERP5/tests/testTemplateTool.py +++ b/product/ERP5/tests/testTemplateTool.py @@ -52,7 +52,7 @@ class TestTemplateTool(ERP5TypeTestCase): def getBusinessTemplateList(self): return ('erp5_core_proxy_field_legacy', - 'erp5_full_text_myisam_catalog', + 'erp5_full_text_mroonga_catalog', 'erp5_base', 'erp5_stock_cache', 'erp5_csv_style') @@ -650,7 +650,7 @@ class TestTemplateTool(ERP5TypeTestCase): 'erp5_core_proxy_field_legacy': first_group, 'erp5_mysql_innodb_catalog': first_group, 'erp5_core': first_group, - 'erp5_full_text_myisam_catalog': first_group, + 'erp5_full_text_mroonga_catalog': first_group, 'erp5_xhtml_style': first_group, 'erp5_ingestion_mysql_innodb_catalog': second_group, 'erp5_base': second_group, diff --git a/product/ERP5Catalog/CatalogTool.py b/product/ERP5Catalog/CatalogTool.py index 95b031349f..bbc75ad133 100644 --- a/product/ERP5Catalog/CatalogTool.py +++ b/product/ERP5Catalog/CatalogTool.py @@ -881,9 +881,10 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject): by looking at the category tree. For exemple it will generate: - destination_title | category,catalog/title/z_related_destination - default_destination_title | category,catalog/title/z_related_destination - strict_destination_title | category,catalog/title/z_related_strict_destination + destination_reference | category,catalog/reference/z_related_destination + default_destination_reference | category,catalog/reference/z_related_destination + strict_destination_reference | category,catalog/reference/z_related_strict_destination + destination_title | category,catalog_full_text/title/z_related_destination strict_ related keys only returns documents which are strictly member of the category. @@ -917,9 +918,18 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject): if related: end_key = end_key[len(related_string):] # XXX: joining with non-catalog tables is not trivial and requires - # ZSQLCatalog's ColumnMapper cooperation, so only allow catalog - # columns. - if 'catalog' in column_map.get(end_key, ()): + # ZSQLCatalog's ColumnMapper cooperation, so only allow columns in + # catalog or catalog_full_text tables. + if end_key != 'uid' and 'catalog_full_text' in column_map.get(end_key, ()): + related_key_list.append( + prefix + key + ' | category,catalog_full_text/' + + end_key + + '/z_related_' + + ('strict_' if strict else '') + + expected_base_cat_id + + ('_related' if related else '') + ) + elif 'catalog' in column_map.get(end_key, ()): is_uid = end_key == 'uid' if is_uid: end_key = 'uid' if related else 'category_uid' diff --git a/product/ERP5Catalog/tests/testArchive.py b/product/ERP5Catalog/tests/testArchive.py index 14c3243a15..306f6beedf 100644 --- a/product/ERP5Catalog/tests/testArchive.py +++ b/product/ERP5Catalog/tests/testArchive.py @@ -49,7 +49,7 @@ class TestArchive(InventoryAPITestCase): def getBusinessTemplateList(self): return InventoryAPITestCase.getBusinessTemplateList(self) + ( 'erp5_archive', - 'erp5_full_text_myisam_catalog', + 'erp5_full_text_mroonga_catalog', ) # Different variables used for this test diff --git a/product/ERP5Catalog/tests/testERP5Catalog.py b/product/ERP5Catalog/tests/testERP5Catalog.py index dea8a17360..f74fd1dd91 100644 --- a/product/ERP5Catalog/tests/testERP5Catalog.py +++ b/product/ERP5Catalog/tests/testERP5Catalog.py @@ -44,7 +44,7 @@ from Products.ERP5Type.tests.utils import createZODBPythonScript, todo_erp5, \ from Products.ZSQLCatalog.ZSQLCatalog import HOT_REINDEXING_FINISHED_STATE,\ HOT_REINDEXING_RECORDING_STATE, HOT_REINDEXING_DOUBLE_INDEXING_STATE from Products.CMFActivity.Errors import ActivityFlushError -from Products.ZSQLCatalog.SQLCatalog import Query, ComplexQuery +from Products.ZSQLCatalog.SQLCatalog import Query, ComplexQuery, SimpleQuery from OFS.ObjectManager import ObjectManager @@ -92,7 +92,7 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): return "ERP5Catalog" def getBusinessTemplateList(self): - return ('erp5_full_text_myisam_catalog', 'erp5_base',) + return ('erp5_full_text_mroonga_catalog', 'erp5_base',) # Different variables used for this test username = 'seb' @@ -124,6 +124,7 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): self.getCategoryTool().region, self.getCategoryTool().group ]: module.manage_delObjects(list(module.objectIds())) + module.reindexObject() # Remove copied sql_connector and catalog if self.new_erp5_sql_connection in self.portal.objectIds(): self.portal.manage_delObjects([self.new_erp5_sql_connection]) @@ -189,7 +190,7 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): person = person_module.newContent(id='1',portal_type='Person') path_list = [person.getRelativeUrl()] self.checkRelativeUrlNotInSQLPathList(path_list) - person.immediateReindexObject() + self.tic() self.checkRelativeUrlInSQLPathList(path_list) person_module.manage_delObjects('1') self.tic() @@ -197,10 +198,10 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): # Now we will ask to immediatly reindex person = person_module.newContent(id='2', portal_type='Person',) - person.immediateReindexObject() + self.tic() path_list = [person.getRelativeUrl()] self.checkRelativeUrlInSQLPathList(path_list) - person.immediateReindexObject() + self.tic() self.checkRelativeUrlInSQLPathList(path_list) person_module.manage_delObjects('2') self.tic() @@ -209,7 +210,7 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): person = person_module.newContent(id='3',portal_type='Person') path_list = [person.getRelativeUrl()] self.checkRelativeUrlNotInSQLPathList(path_list) - person.immediateReindexObject() + self.tic() self.checkRelativeUrlInSQLPathList(path_list) person_module.deleteContent('3') # Now delete things is made with activities @@ -223,10 +224,10 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): folder_object_list = [x.getObject().getId() for x in person_module.searchFolder()] self.assertEqual([],folder_object_list) person = person_module.newContent(id='4',portal_type='Person',) - person.immediateReindexObject() + self.tic() folder_object_list = [x.getObject().getId() for x in person_module.searchFolder()] self.assertEqual(['4'],folder_object_list) - person.immediateReindexObject() + self.tic() person_module.manage_delObjects('4') self.tic() folder_object_list = [x.getObject().getId() for x in person_module.searchFolder()] @@ -240,7 +241,7 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): self.assertEqual([],folder_object_list) person = person_module.newContent(id='4',portal_type='Person') - person.immediateReindexObject() + self.tic() folder_object_list = [x.getObject().getId() for x in person_module.searchFolder()] self.assertEqual(['4'],folder_object_list) @@ -274,7 +275,7 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): portal_catalog.manage_catalogClear() person = person_module.newContent(id='4',portal_type='Person') - person.immediateReindexObject() + self.tic() folder_object_list = [x.getObject().getId() for x in person_module.searchFolder()] self.assertEqual(['4'],folder_object_list) @@ -298,7 +299,7 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): portal_catalog.manage_catalogClear() person = person_module.newContent(id='4',portal_type='Person') - person.immediateReindexObject() + self.tic() folder_object_list = [x.getObject().getId() for x in person_module.searchFolder()] self.assertEqual(['4'],folder_object_list) @@ -310,11 +311,11 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): portal_catalog.manage_catalogClear() person = person_module.newContent(id='a',portal_type='Person',title='a',description='z') - person.immediateReindexObject() + self.tic() person = person_module.newContent(id='b',portal_type='Person',title='a',description='y') - person.immediateReindexObject() + self.tic() person = person_module.newContent(id='c',portal_type='Person',title='a',description='x') - person.immediateReindexObject() + self.tic() folder_object_list = [x.getObject().getId() for x in person_module.searchFolder(sort_on=[('id','ascending')])] self.assertEqual(['a','b','c'],folder_object_list) @@ -335,11 +336,11 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): portal_catalog.manage_catalogClear() person = person_module.newContent(id='a',portal_type='Person',title='1') - person.immediateReindexObject() + self.tic() person = person_module.newContent(id='b',portal_type='Person',title='2') - person.immediateReindexObject() + self.tic() person = person_module.newContent(id='c',portal_type='Person',title='12') - person.immediateReindexObject() + self.tic() folder_object_list = [x.getObject().getTitle() for x in person_module.searchFolder(sort_on=[('title','ascending')])] self.assertEqual(['1','12','2'],folder_object_list) folder_object_list = [x.getObject().getTitle() for x in person_module.searchFolder(sort_on=[('title','ascending','int')])] @@ -654,7 +655,7 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): title = 'Sébastien' person = person_module.newContent(id='5',portal_type='Person',title=title) - person.immediateReindexObject() + self.tic() folder_object_list = [x.getObject().getId() for x in person_module.searchFolder()] self.assertEqual(['5'],folder_object_list) folder_object_list = [x.getObject().getId() for x in @@ -666,7 +667,7 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): title = 'Sébastien' person = person_module.newContent(id='5',portal_type='Person', title=title) - person.immediateReindexObject() + self.tic() folder_object_list = [x.getObject().getId() for x in person_module.searchFolder(title=title)] self.assertEqual(['5'],folder_object_list) @@ -690,10 +691,10 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): portal_category.group.objectIds()]) group_nexedi_category = portal_category.group\ .newContent( id = 'nexedi', title='Nexedi', - description='a') + reference='a') group_nexedi_category2 = portal_category.group\ .newContent( id = 'storever', title='Storever', - description='b') + reference='b') module = portal.getDefaultModule('Organisation') organisation = module.newContent(portal_type='Organisation',) organisation.setGroup('nexedi') @@ -716,17 +717,17 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): organisation_list = [x.getObject() for x in module.searchFolder(group_id='storever')] self.assertEqual(organisation_list,[organisation2]) - # Try to get the organisation with the group description 'a' + # Try to get the organisation with the group reference 'a' organisation_list = [x.getObject() for x in - module.searchFolder(group_description='a')] + module.searchFolder(group_reference='a')] self.assertEqual(organisation_list,[organisation]) - # Try to get the organisation with the group description 'c' + # Try to get the organisation with the group reference 'c' organisation_list = [x.getObject() for x in - module.searchFolder(group_description='c')] + module.searchFolder(group_reference='c')] self.assertEqual(organisation_list,[]) - # Try to get the organisation with the default group description 'c' + # Try to get the organisation with the default group reference 'c' organisation_list = [x.getObject() for x in - module.searchFolder(default_group_description='c')] + module.searchFolder(default_group_reference='c')] self.assertEqual(organisation_list,[]) # Try to get the organisation with group relative_url group_relative_url = group_nexedi_category.getRelativeUrl() @@ -752,10 +753,10 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): portal_category.group.objectIds()]) group_nexedi_category = portal_category.group\ .newContent( id = 'nexedi', title='Nexedi', - description='a') + reference='a') sub_group_nexedi = group_nexedi_category\ .newContent( id = 'erp5', title='ERP5', - description='b') + reference='b') module = portal.getDefaultModule('Organisation') organisation = module.newContent(portal_type='Organisation',) organisation.setGroup('nexedi/erp5') @@ -771,13 +772,13 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): organisation_list = [x.getObject() for x in module.searchFolder(strict_group_title='ERP5')] self.assertEqual(organisation_list,[organisation]) - # Try to get the organisation with the group description a + # Try to get the organisation with the group reference a organisation_list = [x.getObject() for x in - module.searchFolder(strict_group_description='a')] + module.searchFolder(strict_group_reference='a')] self.assertEqual(organisation_list,[]) - # Try to get the organisation with the group description b + # Try to get the organisation with the group reference b organisation_list = [x.getObject() for x in - module.searchFolder(strict_group_description='b')] + module.searchFolder(strict_group_reference='b')] self.assertEqual(organisation_list,[organisation]) def test_22_SearchingWithUnicode(self): @@ -793,7 +794,7 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): # Now we will ask to immediatly reindex person = person_module.newContent(id='2', portal_type='Person',) - person.immediateReindexObject() + self.tic() path_list = [person.getRelativeUrl()] self.checkRelativeUrlInSQLPathList(path_list) # We will delete the connector @@ -855,19 +856,19 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): """Sort-on parameter and related key. (Assumes that region_title is a \ valid related key)""" self.assertTrue( - self.getCatalogTool().buildSQLQuery(region_title='foo', - sort_on=(('region_title', 'ascending'),))['order_by_expression'].endswith('.`title` ASC')) + self.getCatalogTool().buildSQLQuery(region_reference='foo', + sort_on=(('region_reference', 'ascending'),))['order_by_expression'].endswith('.`reference` ASC')) self.assertTrue( - self.getCatalogTool().buildSQLQuery(region_title='foo', - sort_on=(('region_title', 'descending'),))['order_by_expression'].endswith('.`title` DESC')) + self.getCatalogTool().buildSQLQuery(region_reference='foo', + sort_on=(('region_reference', 'descending'),))['order_by_expression'].endswith('.`reference` DESC')) self.assertTrue( self.getCatalogTool().buildSQLQuery( - sort_on=(('region_title', 'ascending'),))['order_by_expression'].endswith('.`title` ASC'), + sort_on=(('region_reference', 'ascending'),))['order_by_expression'].endswith('.`reference` ASC'), 'sort_on parameter must be taken into account even if related key ' 'is not a parameter of the current query') self.assertTrue( self.getCatalogTool().buildSQLQuery( - sort_on=(('region_title', 'descending'),))['order_by_expression'].endswith('.`title` DESC'), + sort_on=(('region_reference', 'descending'),))['order_by_expression'].endswith('.`reference` DESC'), 'sort_on parameter must be taken into account even if related key ' 'is not a parameter of the current query') @@ -957,8 +958,8 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): self.assertEqual([organisation.getPath()], [x.path for x in self.getCatalogTool()( - title={'query': (organisation_title, 'something else'), - 'operator': 'or'})]) + **{'catalog.title':{'query': (organisation_title, 'something else'), + 'operator': 'or'}})]) def test_33_SimpleQueryDictWithAndOperator(self): """use a dict as a keyword parameter, with AND operator. @@ -1149,20 +1150,19 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): SearchableText='title')[0][0]) # 'different' is found in more than 50% of records - # MySQL ignores such a word, but Tritonn does not ignore. - try: - self.portal.erp5_sql_connection.manage_test('SHOW SENNA STATUS') - except ProgrammingError: + # MySQL ignores such a word, but Mroonga does not ignore. + if 'ENGINE=Mroonga' in self.portal.erp5_sql_connection.manage_test( + 'SHOW CREATE TABLE full_text')[0][1]: + # Mroonga + self.assertEqual(10, self.getCatalogTool().countResults( + portal_type='Organisation', SearchableText='different')[0][0]) + else: # MySQL self.assertEqual([], [x.getObject for x in self.getCatalogTool()( portal_type='Organisation', SearchableText='different')]) self.assertEqual(0, self.getCatalogTool().countResults( portal_type='Organisation', SearchableText='different')[0][0]) - else: - # Tritonn - self.assertEqual(10, self.getCatalogTool().countResults( - portal_type='Organisation', SearchableText='different')[0][0]) def test_43_ManagePasteObject(self): portal_catalog = self.getCatalogTool() @@ -1221,11 +1221,11 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): # Recursive Complex Query # (title='abc' and description='abc') OR # title='foo' and description='bar' - catalog_kw = {'query':ComplexQuery(ComplexQuery(Query(title='abc'), - Query(description='abc'), + catalog_kw = {'query':ComplexQuery(ComplexQuery(SimpleQuery(title='abc'), + SimpleQuery(description='abc'), operator='AND'), - ComplexQuery(Query(title='foo'), - Query(description='bar'), + ComplexQuery(SimpleQuery(title='foo'), + SimpleQuery(description='bar'), operator='AND'), operator='OR')} self.failIfDifferentSet([org_a.getPath(), org_f.getPath()], @@ -1578,11 +1578,11 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): catalog = portal_catalog.objectValues()[0] person = person_module.newContent(id='a',portal_type='Person',title='a',description='z') - person.immediateReindexObject() + self.tic() person = person_module.newContent(id='b',portal_type='Person',title='a',description='y') - person.immediateReindexObject() + self.tic() person = person_module.newContent(id='c',portal_type='Person',title='a',description='x') - person.immediateReindexObject() + self.tic() index_columns = getattr(catalog, 'sql_catalog_index_on_order_keys', None) self.assertNotEqual(index_columns, None) self.assertEqual(len(index_columns), 0) @@ -2105,7 +2105,7 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor): # description is not a keyword by default. (This might change in the # future, in this case, this test have to be updated) self.assertSameSet([doc], [x.getObject() for x in - ctool(portal_type='Organisation', description='Foo')]) + ctool(portal_type='Organisation', description='=Foo')]) self.assertEqual({doc, other_doc}, {x.getObject() for x in ctool(portal_type='Organisation', description=dict(query='Foo', key='Keyword'))}) @@ -3546,19 +3546,19 @@ VALUES portal_category.group.objectIds()]) group_nexedi_category = portal_category.group\ .newContent( id = 'nexedi', title='Nexedi', - description='a') + reference='a') group_nexedi_category2 = portal_category.group\ .newContent( id = 'storever', title='Storever', - description='b') + reference='b') module = portal.getDefaultModule('Organisation') organisation = module.newContent(portal_type='Organisation', title='Nexedi Orga', - description='c') + reference='c') organisation.setGroup('nexedi') self.assertEqual(organisation.getGroupValue(), group_nexedi_category) organisation2 = module.newContent(portal_type='Organisation', title='Storever Orga', - description='d') + reference='d') organisation2.setGroup('storever') organisation2.setTitle('Organisation 2') self.assertEqual(organisation2.getGroupValue(), group_nexedi_category2) @@ -3580,19 +3580,19 @@ VALUES category_list = [x.getObject() for x in base_category.searchFolder(group_related_id='storever')] self.assertEqual(category_list,[group_nexedi_category2]) - # Try to get the category with the group related organisation description 'd' + # Try to get the category with the group related organisation reference 'd' category_list = [x.getObject() for x in - base_category.searchFolder(group_related_description='d')] + base_category.searchFolder(group_related_reference='d')] self.assertEqual(category_list,[group_nexedi_category2]) - # Try to get the category with the group related organisation description + # Try to get the category with the group related organisation reference # 'e' category_list = [x.getObject() for x in - base_category.searchFolder(group_related_description='e')] + base_category.searchFolder(group_related_reference='e')] self.assertEqual(category_list,[]) - # Try to get the category with the default group related organisation description + # Try to get the category with the default group related organisation reference # 'e' category_list = [x.getObject() for x in - base_category.searchFolder(default_group_related_description='e')] + base_category.searchFolder(default_group_related_reference='e')] self.assertEqual(category_list,[]) # Try to get the category with the group related organisation relative_url organisation_relative_url = organisation.getRelativeUrl() @@ -3618,19 +3618,19 @@ VALUES portal_category.group.objectIds()]) group_nexedi_category = portal_category.group\ .newContent( id = 'nexedi', title='Nexedi', - description='a') + reference='a') sub_group_nexedi = group_nexedi_category\ .newContent( id = 'erp5', title='ERP5', - description='b') + reference='b') module = portal.getDefaultModule('Organisation') organisation = module.newContent(portal_type='Organisation', title='ERP5 Orga', - description='c') + reference='c') organisation.setGroup('nexedi/erp5') self.assertEqual(organisation.getGroupValue(), sub_group_nexedi) organisation2 = module.newContent(portal_type='Organisation', title='Nexedi Orga', - description='d') + reference='d') organisation2.setGroup('nexedi') # Flush message queue self.tic() @@ -3649,15 +3649,15 @@ VALUES base_category.portal_catalog( strict_group_related_title='ERP5 Orga')] self.assertEqual(category_list,[sub_group_nexedi]) - # Try to get the category with the group related organisation description d + # Try to get the category with the group related organisation reference d category_list = [x.getObject() for x in base_category.portal_catalog( - strict_group_related_description='d')] + strict_group_related_reference='d')] self.assertEqual(category_list,[group_nexedi_category]) - # Try to get the category with the group related organisation description c + # Try to get the category with the group related organisation reference c category_list = [x.getObject() for x in base_category.portal_catalog( - strict_group_related_description='c')] + strict_group_related_reference='c')] self.assertEqual(category_list,[sub_group_nexedi]) def test_EscapingLoginInSescurityQuery(self): @@ -3768,7 +3768,7 @@ VALUES title='foo (bar)' person = person_module.newContent(portal_type='Person',title=title) person_id = person.getId() - person.immediateReindexObject() + self.tic() folder_object_list = [x.getObject().getId() for x in person_module.searchFolder()] self.assertTrue(person_id in folder_object_list) folder_object_list = [x.getObject().getId() for x in @@ -3781,15 +3781,16 @@ VALUES # Make sure that the catalog will not split it with such research : # title=foo AND title=bar title='foo bar' - person_module.newContent(portal_type='Person',title=title).immediateReindexObject() + person_module.newContent(portal_type='Person',title=title) + self.tic() title = title.replace(' ', ' ') person = person_module.newContent(portal_type='Person',title=title) person_id = person.getId() - person.immediateReindexObject() + self.tic() folder_object_list = [x.getObject().getId() for x in person_module.searchFolder()] self.assertTrue(person_id in folder_object_list) folder_object_list = [x.getObject().getId() for x in - person_module.searchFolder(title=title)] + person_module.searchFolder(**{'catalog.title':title})] self.assertEqual([person_id],folder_object_list) def test_SearchFolderWithSingleQuote(self): @@ -3800,7 +3801,7 @@ VALUES title="foo 'bar" person = person_module.newContent(portal_type='Person',title=title) person_id = person.getId() - person.immediateReindexObject() + self.tic() folder_object_list = [x.getObject().getId() for x in person_module.searchFolder()] self.assertTrue(person_id in folder_object_list) folder_object_list = [x.getObject().getId() for x in @@ -3817,7 +3818,7 @@ VALUES person = person_module.newContent(portal_type='Person',title=title, description=description) person_uid = person.getUid() - person.immediateReindexObject() + self.tic() folder_object_list = person_module.searchFolder(uid=person_uid, select_dict={'title': None}) new_title = 'bar' new_description = 'foobarfoo' diff --git a/product/ERP5Catalog/tests/testERP5CatalogSecurityUidOptimization.py b/product/ERP5Catalog/tests/testERP5CatalogSecurityUidOptimization.py index dcfc5f9fde..9e1a75fc57 100644 --- a/product/ERP5Catalog/tests/testERP5CatalogSecurityUidOptimization.py +++ b/product/ERP5Catalog/tests/testERP5CatalogSecurityUidOptimization.py @@ -42,7 +42,7 @@ class TestERP5CatalogSecurityUidOptimization(ERP5TypeTestCase): XXX: Inherit from TestERP5Catalog so we test default and security_uid optmization with same tests. """ business_template_list = ['erp5_security_uid_innodb_catalog', - 'erp5_full_text_myisam_catalog','erp5_base'] + 'erp5_full_text_mroonga_catalog','erp5_base'] def getBusinessTemplateList(self): return self.business_template_list diff --git a/product/ERP5Configurator/tests/ConfiguratorTestMixin.py b/product/ERP5Configurator/tests/ConfiguratorTestMixin.py index ca550ee966..70b306758b 100644 --- a/product/ERP5Configurator/tests/ConfiguratorTestMixin.py +++ b/product/ERP5Configurator/tests/ConfiguratorTestMixin.py @@ -85,7 +85,7 @@ class TestLiveConfiguratorWorkflowMixin(SecurityTestCase): def getBusinessTemplateList(self): return ('erp5_core_proxy_field_legacy', - 'erp5_full_text_myisam_catalog', + 'erp5_full_text_mroonga_catalog', 'erp5_base', 'erp5_workflow', 'erp5_configurator', diff --git a/product/ERP5Configurator/tests/testConfiguratorItem.py b/product/ERP5Configurator/tests/testConfiguratorItem.py index 132bf77da6..87d79d023f 100644 --- a/product/ERP5Configurator/tests/testConfiguratorItem.py +++ b/product/ERP5Configurator/tests/testConfiguratorItem.py @@ -43,7 +43,7 @@ class TestConfiguratorItem(TestLiveConfiguratorWorkflowMixin): def getBusinessTemplateList(self): return ('erp5_core_proxy_field_legacy', - 'erp5_full_text_myisam_catalog', + 'erp5_full_text_mroonga_catalog', 'erp5_base', 'erp5_workflow', 'erp5_configurator', diff --git a/product/ERP5Configurator/tests/testConfiguratorTool.py b/product/ERP5Configurator/tests/testConfiguratorTool.py index f04b8cd989..57f29f4de9 100644 --- a/product/ERP5Configurator/tests/testConfiguratorTool.py +++ b/product/ERP5Configurator/tests/testConfiguratorTool.py @@ -38,7 +38,7 @@ class TestConfiguratorTool(TestLiveConfiguratorWorkflowMixin): def getBusinessTemplateList(self): return ('erp5_core_proxy_field_legacy', - 'erp5_full_text_myisam_catalog', + 'erp5_full_text_mroonga_catalog', 'erp5_base', 'erp5_workflow', 'erp5_configurator', diff --git a/product/ERP5Configurator/tests/testFunctionalConfigurator.py b/product/ERP5Configurator/tests/testFunctionalConfigurator.py index e66f646f2b..fcb01f0d04 100644 --- a/product/ERP5Configurator/tests/testFunctionalConfigurator.py +++ b/product/ERP5Configurator/tests/testFunctionalConfigurator.py @@ -47,7 +47,7 @@ class TestZeleniumConfiguratorStandard(ERP5TypeFunctionalTestCase): """ Return the list of business templates. """ - return ('erp5_core_proxy_field_legacy', 'erp5_full_text_myisam_catalog', + return ('erp5_core_proxy_field_legacy', 'erp5_full_text_mroonga_catalog', 'erp5_base', 'erp5_workflow', 'erp5_configurator', 'erp5_configurator_standard', 'erp5_jquery', 'erp5_ui_test_core', 'erp5_accounting', diff --git a/product/ERP5Form/Tool/SelectionTool.py b/product/ERP5Form/Tool/SelectionTool.py index 9619155831..c86f72d466 100644 --- a/product/ERP5Form/Tool/SelectionTool.py +++ b/product/ERP5Form/Tool/SelectionTool.py @@ -1271,7 +1271,8 @@ class SelectionTool( BaseTool, SimpleItem ): if len(field_value): sql_catalog = self.portal_catalog.getSQLCatalog() field_value = sql_catalog.buildQuery({ - catalog_index: field_value.splitlines() + catalog_index:{'query':field_value.splitlines(), + 'key':'ExactMatch',}, }).asSearchTextExpression(sql_catalog, column='') REQUEST.form[field_key] = field_value diff --git a/product/ERP5OOo/tests/testDms.py b/product/ERP5OOo/tests/testDms.py index 81abcd9617..7d34cda0cd 100644 --- a/product/ERP5OOo/tests/testDms.py +++ b/product/ERP5OOo/tests/testDms.py @@ -103,7 +103,7 @@ class TestDocumentMixin(ERP5TypeTestCase): business_template_list = ['erp5_core_proxy_field_legacy', 'erp5_jquery', - 'erp5_full_text_myisam_catalog', + 'erp5_full_text_mroonga_catalog', 'erp5_base', 'erp5_ingestion_mysql_innodb_catalog', 'erp5_ingestion', @@ -1155,13 +1155,13 @@ class TestDocument(TestDocumentMixin): self.assertSameSet([document_1,web_page_1], getAdvancedSearchStringResultList(**kw)) # exact word search - kw = {'searchabletext_any': '*', + kw = {'searchabletext_any': '', 'searchabletext_phrase': 'linux python'} self.assertSameSet([document_1], getAdvancedSearchStringResultList(**kw)) - kw = {'searchabletext_any': '*', + kw = {'searchabletext_any': '', 'searchabletext_phrase': 'python linux'} self.assertSameSet([document_2], getAdvancedSearchStringResultList(**kw)) - kw = {'searchabletext_any': '*', + kw = {'searchabletext_any': '', 'searchabletext_phrase': 'python linux knowledge system'} self.assertSameSet([document_2], getAdvancedSearchStringResultList(**kw)) @@ -1243,7 +1243,7 @@ class TestDocument(TestDocumentMixin): # should return all documents matching a word no matter of contributor self.assertSameSet([web_page_1, document_4], getAdvancedSearchStringResultList(**kw)) kw = {'searchabletext_any': 'owner', - 'contributor_title': '%Contributor%'} + 'contributor_title': 'Contributor'} self.assertSameSet([document_4], getAdvancedSearchStringResultList(**kw)) # multiple portal_type specified diff --git a/product/ERP5OOo/tests/testOOoDynamicStyle.py b/product/ERP5OOo/tests/testOOoDynamicStyle.py index c1b180823d..c57f82753f 100644 --- a/product/ERP5OOo/tests/testOOoDynamicStyle.py +++ b/product/ERP5OOo/tests/testOOoDynamicStyle.py @@ -52,7 +52,7 @@ class TestOooDynamicStyle(ERP5TypeTestCase): def getBusinessTemplateList(self): return ('erp5_core_proxy_field_legacy', - 'erp5_full_text_myisam_catalog', + 'erp5_full_text_mroonga_catalog', 'erp5_base', 'erp5_ingestion_mysql_innodb_catalog', 'erp5_ingestion', diff --git a/product/ERP5TioSafe/tests/testTioSafeMixin.py b/product/ERP5TioSafe/tests/testTioSafeMixin.py index 43a6efe656..75133d63ac 100644 --- a/product/ERP5TioSafe/tests/testTioSafeMixin.py +++ b/product/ERP5TioSafe/tests/testTioSafeMixin.py @@ -49,7 +49,7 @@ class testTioSafeMixin(ERP5TypeTestCase): """ Return the list of BT required by unit tests. """ return ( 'erp5_core_proxy_field_legacy', - 'erp5_full_text_myisam_catalog', + 'erp5_full_text_mroonga_catalog', 'erp5_base', 'erp5_pdm', 'erp5_simulation', diff --git a/product/ERP5Type/tests/testFunctionalAnonymousSelection.py b/product/ERP5Type/tests/testFunctionalAnonymousSelection.py index 436f19a34e..8dd6675ec7 100644 --- a/product/ERP5Type/tests/testFunctionalAnonymousSelection.py +++ b/product/ERP5Type/tests/testFunctionalAnonymousSelection.py @@ -41,7 +41,7 @@ class TestAnonymousSelection(TestZeleniumCore): """ Return the list of business templates. """ - return ('erp5_core_proxy_field_legacy', 'erp5_full_text_myisam_catalog', + return ('erp5_core_proxy_field_legacy', 'erp5_full_text_mroonga_catalog', 'erp5_base', 'erp5_ui_test_core', 'erp5_ui_test', 'erp5_forge', ) diff --git a/product/ERP5Type/tests/testFunctionalCore.py b/product/ERP5Type/tests/testFunctionalCore.py index 7e78098f54..22b8c6238d 100644 --- a/product/ERP5Type/tests/testFunctionalCore.py +++ b/product/ERP5Type/tests/testFunctionalCore.py @@ -39,7 +39,7 @@ class TestZeleniumCore(ERP5TypeFunctionalTestCase): """ Return the list of business templates. """ - return ('erp5_core_proxy_field_legacy', 'erp5_full_text_myisam_catalog', + return ('erp5_core_proxy_field_legacy', 'erp5_full_text_mroonga_catalog', 'erp5_base', 'erp5_ui_test_core', 'erp5_ui_test', 'erp5_forge', 'erp5_dhtml_style', 'erp5_dhtml_ui_test', 'erp5_jquery', 'erp5_jquery_ui', diff --git a/product/ERP5Type/tests/testFunctionalKM.py b/product/ERP5Type/tests/testFunctionalKM.py index d01f2a162f..49140e6888 100644 --- a/product/ERP5Type/tests/testFunctionalKM.py +++ b/product/ERP5Type/tests/testFunctionalKM.py @@ -43,7 +43,7 @@ class TestZeleniumKM(ERP5TypeFunctionalTestCase): """ # XXX This is a rough list, we should drop as much as we can, and # keep only minimal - return ('erp5_core_proxy_field_legacy', 'erp5_full_text_myisam_catalog', + return ('erp5_core_proxy_field_legacy', 'erp5_full_text_mroonga_catalog', 'erp5_base', 'erp5_ui_test_core', 'erp5_ui_test', 'erp5_forge', 'erp5_dhtml_style', 'erp5_dhtml_ui_test', 'erp5_jquery', 'erp5_jquery_ui', diff --git a/product/ERP5Type/tests/testFunctionalStandaloneUserTutorial.py b/product/ERP5Type/tests/testFunctionalStandaloneUserTutorial.py index 42c84fe845..736300a595 100644 --- a/product/ERP5Type/tests/testFunctionalStandaloneUserTutorial.py +++ b/product/ERP5Type/tests/testFunctionalStandaloneUserTutorial.py @@ -48,7 +48,7 @@ class TestZeleniumStandaloneUserTutorial(ERP5TypeFunctionalTestCase): """ Return the list of business templates. """ - return ('erp5_core_proxy_field_legacy', 'erp5_full_text_myisam_catalog', + return ('erp5_core_proxy_field_legacy', 'erp5_full_text_mroonga_catalog', 'erp5_base', 'erp5_ui_test_core', 'erp5_forge', 'erp5_dhtml_style', 'erp5_jquery', 'erp5_jquery_ui', diff --git a/product/ZMySQLDA/tests/testDeferredConnection.py b/product/ZMySQLDA/tests/testDeferredConnection.py index 53207836a7..771d028210 100644 --- a/product/ZMySQLDA/tests/testDeferredConnection.py +++ b/product/ZMySQLDA/tests/testDeferredConnection.py @@ -65,7 +65,7 @@ class TestDeferredConnection(ERP5TypeTestCase): """ def getBusinessTemplateList(self): - return 'erp5_full_text_myisam_catalog', + return 'erp5_full_text_mroonga_catalog', def getTitle(self): return "Deferred Connection" diff --git a/product/ZSQLCatalog/Operator/ComparisonOperator.py b/product/ZSQLCatalog/Operator/ComparisonOperator.py index f152ccea8d..40a8fcd432 100644 --- a/product/ZSQLCatalog/Operator/ComparisonOperator.py +++ b/product/ZSQLCatalog/Operator/ComparisonOperator.py @@ -33,6 +33,7 @@ from Products.ZSQLCatalog.SQLExpression import SQLExpression from Products.ZSQLCatalog.interfaces.operator import IOperator from zope.interface.verify import verifyClass from Products.ZSQLCatalog.SQLCatalog import list_type_list +import re class ComparisonOperatorBase(OperatorBase): def asSQLExpression(self, column, value_list, only_group_columns): @@ -105,13 +106,17 @@ class MatchComparisonOperator(MonovaluedComparisonOperator): This operator can emit a select expression, so it overrides asSQLExpression inseatd of just defining a render method. """ + # No need to do full text search for an empty string. + if value_list == '': + column, value_list = self.render(column, value_list) + return SQLExpression(self, where_expression='%s %s %s' % (column, '=', value_list)) match_string = self.where_expression_format_string % { 'column': column, 'value_list': self.renderValue(value_list), } select_dict = {} if not only_group_columns: - select_dict[column.replace('`', '').split('.')[-1]] = match_string + select_dict['%s__score__' % column.replace('`', '').rsplit('.', 1)[-1]] = match_string # Sort on this column uses relevance. # TODO: Add a way to allow sorting by raw column value. order_by_dict = { @@ -127,6 +132,50 @@ class MatchComparisonOperator(MonovaluedComparisonOperator): verifyClass(IOperator, MatchComparisonOperator) +class MroongaComparisonOperator(MatchComparisonOperator): + fulltext_boolean_splitter = re.compile(r'(\s|\(.+?\)|".+?")') + fulltext_boolean_detector = re.compile(r'(^[+-]|^.+\*$|^["(].+[")]$)') + + def __init__(self, operator, force_boolean=False): + MatchComparisonOperator.__init__(self, operator, ' IN BOOLEAN MODE') + self.force_boolean = force_boolean + + def renderValue(self, value_list): + """ + Special Query renderer for MroongaFullText queries: + * by default 'AND' search by using '*D+' pragma. + * similarity search for non-boolean queries by using '*S"..."' operator. + """ + if isinstance(value_list, list_type_list): + try: + value_list, = value_list + except ValueError: + raise ValueError, '%r: value_list must not contain more than one item. Got %r' % (self, value_list) + + if self.force_boolean: + fulltext_query = '*D+ %s' % value_list + return self._renderValue(fulltext_query) + else: + match_query_list = [] + match_boolean_query_list = [] + for token in self.fulltext_boolean_splitter.split(value_list): + token = token.strip() + if not token: + continue + elif self.fulltext_boolean_detector.match(token): + match_boolean_query_list.append(token) + else: + match_query_list.append(token) + # Always use BOOLEAN MODE to combine similarity search and boolean search. + fulltext_query = '*D+' + if match_query_list: + fulltext_query += ' *S"%s"' % ' '.join(match_query_list) + if match_boolean_query_list: + fulltext_query += ' %s' % ' '.join(match_boolean_query_list) + return self._renderValue(fulltext_query) + +verifyClass(IOperator, MroongaComparisonOperator) + class SphinxSEComparisonOperator(MonovaluedComparisonOperator): def __init__(self, operator, mode=''): MonovaluedComparisonOperator.__init__(self, operator, '') @@ -173,9 +222,10 @@ operator_dict = { 'match': MatchComparisonOperator('match'), 'match_boolean': MatchComparisonOperator('match_boolean', mode=' IN BOOLEAN MODE'), 'match_expansion': MatchComparisonOperator('match_expansion', mode=' WITH QUERY EXPANSION'), + 'mroonga': MroongaComparisonOperator('mroonga'), + 'mroonga_boolean': MroongaComparisonOperator('mroonga_boolean', force_boolean=True), 'sphinxse': SphinxSEComparisonOperator('sphinxse'), 'in': MultivaluedComparisonOperator('in'), 'is': MonovaluedComparisonOperator('is'), 'is not': MonovaluedComparisonOperator('is not', '!='), } - diff --git a/product/ZSQLCatalog/Query/RelatedQuery.py b/product/ZSQLCatalog/Query/RelatedQuery.py index 859f65bcf7..1ddb4f44f4 100644 --- a/product/ZSQLCatalog/Query/RelatedQuery.py +++ b/product/ZSQLCatalog/Query/RelatedQuery.py @@ -62,12 +62,14 @@ class RelatedQuery(Query): self.table_alias_list = table_alias_list def _asSearchTextExpression(self, sql_catalog, column=None): - assert column is None + assert column in (None, '') + if column is None: + column = self.search_key.getColumn() join_condition = self.join_condition if join_condition is None: result = None else: - result = join_condition.asSearchTextExpression(sql_catalog, column=self.search_key.getColumn()) + result = join_condition.asSearchTextExpression(sql_catalog, column=column) return False, result def asSQLExpression(self, sql_catalog, column_map, only_group_columns): diff --git a/product/ZSQLCatalog/SQLExpression.py b/product/ZSQLCatalog/SQLExpression.py index 6750c3dac0..128bbe6aae 100644 --- a/product/ZSQLCatalog/SQLExpression.py +++ b/product/ZSQLCatalog/SQLExpression.py @@ -334,6 +334,9 @@ class SQLExpression(object): if can_merge_sql_expression and alias in mergeable_set: # Custom conflict resolution column = '%s + %s' % (existing_value, column) + elif alias.endswith('__score__'): + # We only support the first full text score in select dict. + pass else: message = '%r is a known alias for column %r, can\'t alias it now to column %r' % (alias, existing_value, column) if DEBUG: diff --git a/product/ZSQLCatalog/SearchKey/FullTextKey.py b/product/ZSQLCatalog/SearchKey/FullTextKey.py index f01e84976c..fb868a48b1 100644 --- a/product/ZSQLCatalog/SearchKey/FullTextKey.py +++ b/product/ZSQLCatalog/SearchKey/FullTextKey.py @@ -28,29 +28,30 @@ # ############################################################################## -from SearchKey import SearchKey +from DefaultKey import DefaultKey from Products.ZSQLCatalog.Query.SimpleQuery import SimpleQuery -from Products.ZSQLCatalog.SearchText import parse from Products.ZSQLCatalog.interfaces.search_key import ISearchKey +from Products.ZSQLCatalog.SearchText import dequote from zope.interface.verify import verifyClass import re FULLTEXT_BOOLEAN_DETECTOR = re.compile(r'.*((^|\s)[\+\-<>\(\~]|[\*\)](\s|$))') -class FullTextKey(SearchKey): +class FullTextKey(DefaultKey): """ This SearchKey generates SQL fulltext comparisons. """ default_comparison_operator = 'match' get_operator_from_value = False - def parseSearchText(self, value, is_column): - return parse(value, is_column) - def dequoteParsedText(self): return False def _renderValueAsSearchText(self, value, operator): + # XXX: + # return value for 'a b' here is '(a b), but keyword search with + # '(a b)' means fulltext search with (a OR b), that is different + # from fulltext='a b' that means fulltext search with (a AND b). return '(%s)' % (value, ) def _processSearchValue(self, search_value, logical_operator, @@ -61,8 +62,8 @@ class FullTextKey(SearchKey): mode, make the operator for that value be 'match_boolean'. """ operator_value_dict, logical_operator, parsed = \ - SearchKey._processSearchValue(self, search_value, logical_operator, - comparison_operator) + super(FullTextKey, self)._processSearchValue( + search_value, logical_operator, comparison_operator) new_value_list = [] append = new_value_list.append for value in operator_value_dict.pop('match', []): @@ -77,6 +78,13 @@ class FullTextKey(SearchKey): operator_value_dict['match_boolean'].extend(new_value_list) else: operator_value_dict['match'] = new_value_list + # Dequote for non full-text queries. + for comparison_operator, value_list in operator_value_dict.iteritems(): + if comparison_operator not in ('match', 'match_boolean'): + operator_value_dict[comparison_operator] = [ + isinstance(value, basestring) and dequote(value) or value + for value in value_list + ] return operator_value_dict, logical_operator, parsed def _buildQuery(self, operator_value_dict, logical_operator, parsed, group): @@ -88,10 +96,20 @@ class FullTextKey(SearchKey): column = self.getColumn() query_list = [] append = query_list.append - for comparison_operator, value_list in operator_value_dict.iteritems(): + for comparison_operator in ('match', 'match_boolean'): + value_list = operator_value_dict.pop(comparison_operator, []) + if not value_list: + continue + # XXX: + # In MySQL FTS, no operator implies OR so that we should not merge + # AND queries into one... append(SimpleQuery(search_key=self, comparison_operator=comparison_operator, group=group, **{column: ' '.join(value_list)})) + # Other comparison operators are handled by the super class. + if operator_value_dict: + query_list += super(FullTextKey, self)._buildQuery( + operator_value_dict, logical_operator, parsed, group) return query_list verifyClass(ISearchKey, FullTextKey) diff --git a/product/ZSQLCatalog/SearchKey/MroongaBooleanFullTextKey.py b/product/ZSQLCatalog/SearchKey/MroongaBooleanFullTextKey.py new file mode 100644 index 0000000000..d6977a4371 --- /dev/null +++ b/product/ZSQLCatalog/SearchKey/MroongaBooleanFullTextKey.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2014 Nexedi SA and Contributors. All Rights Reserved. +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsibility of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# guarantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +############################################################################## + +from MroongaFullTextKey import MroongaFullTextKey +from Products.ZSQLCatalog.interfaces.search_key import ISearchKey +from zope.interface.verify import verifyClass + +class MroongaBooleanFullTextKey(MroongaFullTextKey): + """ + This SearchKey generates SQL fulltext comparisons for Mroonga whose + default comparison operator is mroonga_boolean. + """ + default_comparison_operator = 'mroonga_boolean' + +verifyClass(ISearchKey, MroongaBooleanFullTextKey) diff --git a/product/ZSQLCatalog/SearchKey/MroongaFullTextKey.py b/product/ZSQLCatalog/SearchKey/MroongaFullTextKey.py new file mode 100644 index 0000000000..e941790a0b --- /dev/null +++ b/product/ZSQLCatalog/SearchKey/MroongaFullTextKey.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2014-2006 Nexedi SA and Contributors. All Rights Reserved. +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsibility of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# guarantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +############################################################################## + +from DefaultKey import DefaultKey +from Products.ZSQLCatalog.Query.SimpleQuery import SimpleQuery +from Products.ZSQLCatalog.interfaces.search_key import ISearchKey +from Products.ZSQLCatalog.SearchText import dequote +from zope.interface.verify import verifyClass + +class MroongaFullTextKey(DefaultKey): + default_comparison_operator = 'mroonga' + + def dequoteParsedText(self): + return False + + def _renderValueAsSearchText(self, value, operator): + # XXX: + # return value for 'a b' here is '(a b), but keyword search with + # '(a b)' means fulltext search with (a OR b), that is different + # from fulltext='a b' that means fulltext search with (a AND b). + return '(%s)' % (value, ) + + def _processSearchValue(self, search_value, logical_operator, + comparison_operator): + operator_value_dict, logical_operator, parsed = \ + super(MroongaFullTextKey, self)._processSearchValue( + search_value, logical_operator, comparison_operator) + # Dequote for non full-text queries. + for comparison_operator, value_list in operator_value_dict.iteritems(): + if comparison_operator not in ('mroonga', 'mroonga_boolean'): + operator_value_dict[comparison_operator] = [ + isinstance(value, basestring) and dequote(value) or value + for value in value_list + ] + return operator_value_dict, logical_operator, parsed + + def _buildQuery(self, operator_value_dict, logical_operator, parsed, group): + """ + Special Query builder for FullText queries: merge all values having the + same operator into just one query, to save SQL server from the burden to + do multiple fulltext lookups when one would suit the purpose. + """ + column = self.getColumn() + query_list = [] + append = query_list.append + for comparison_operator in ('mroonga', 'mroonga_boolean'): + value_list = operator_value_dict.pop(comparison_operator, []) + if not value_list: + continue + if logical_operator == 'and': + joined_value = ' '.join(value_list) + append(SimpleQuery(search_key=self, + comparison_operator=comparison_operator, + group=group, **{column:joined_value})) + else: + # TODO : We can join to one query like 'aaa OR (bbb ccc) OR "ddd eee"'. + for value in value_list: + append(SimpleQuery(search_key=self, + comparison_operator=comparison_operator, + group=group, **{column:value})) + # Other comparison operators are handled by the super class. + if operator_value_dict: + query_list += super(MroongaFullTextKey, self)._buildQuery( + operator_value_dict, logical_operator, parsed, group) + return query_list + +verifyClass(ISearchKey, MroongaFullTextKey) diff --git a/product/ZSQLCatalog/tests/testSQLCatalog.py b/product/ZSQLCatalog/tests/testSQLCatalog.py index 0837aa9949..5ad28f4440 100644 --- a/product/ZSQLCatalog/tests/testSQLCatalog.py +++ b/product/ZSQLCatalog/tests/testSQLCatalog.py @@ -168,8 +168,10 @@ class DummyCatalog(SQLCatalog): sql_catalog_keyword_search_keys = ('keyword', ) sql_catalog_datetime_search_keys = ('date', ) - sql_catalog_full_text_search_keys = ('fulltext', ) + sql_catalog_full_text_search_keys = ('old_fulltext', ) sql_catalog_scriptable_keys = ('scriptable_keyword | scriptableKeyScript', ) + sql_catalog_search_keys = ('fulltext | MroongaFullTextKey', + 'fulltext_boolean | MroongaBooleanFullTextKey',) def getColumnMap(self): """ @@ -180,7 +182,9 @@ class DummyCatalog(SQLCatalog): 'default': ['foo', ], 'keyword': ['foo', ], 'date': ['foo', ], + 'old_fulltext': ['foo', ], 'fulltext': ['foo', ], + 'fulltext_boolean': ['foo', ], 'other_uid': ['bar', ], 'ambiguous_mapping': ['foo', 'bar'], } @@ -495,8 +499,8 @@ class TestSQLCatalog(ERP5TypeTestCase): # This example introduces impossible-to-merge search text criterion, which # is allowed as long as reference_query = ReferenceQuery( - ReferenceQuery(ReferenceQuery(operator='match', fulltext='a'), - ReferenceQuery(ReferenceQuery(operator='match', fulltext='b'), + ReferenceQuery(ReferenceQuery(operator='mroonga', fulltext='a'), + ReferenceQuery(ReferenceQuery(operator='mroonga', fulltext='b'), operator='not'), operator='and'), operator='and') self.catalog(reference_query, {'fulltext': 'a NOT b'}) # The same, with an order by, must raise @@ -504,15 +508,15 @@ class TestSQLCatalog(ERP5TypeTestCase): {'fulltext': 'a NOT b', 'order_by_list': [('fulltext', ), ]}, check_search_text=False) # If one want to sort on, he must use the equivalent FullText syntax: - self.catalog(ReferenceQuery(ReferenceQuery(operator='match_boolean', + self.catalog(ReferenceQuery(ReferenceQuery(operator='mroonga', fulltext=MatchList(['a -b', '-b a'])), operator='and'), {'fulltext': 'a -b', 'order_by_list': [('fulltext', ), ]}, check_search_text=False) - self.catalog(ReferenceQuery(ReferenceQuery(ReferenceQuery(operator='match', fulltext='a'), - ReferenceQuery(ReferenceQuery(operator='match', fulltext='b'), operator='not'), operator='or'), operator='and'), + self.catalog(ReferenceQuery(ReferenceQuery(ReferenceQuery(operator='mroonga', fulltext='a'), + ReferenceQuery(ReferenceQuery(operator='mroonga', fulltext='b'), operator='not'), operator='or'), operator='and'), {'fulltext': 'a OR NOT b'}) - self.catalog(ReferenceQuery(ReferenceQuery(ReferenceQuery(operator='match', fulltext='a'), - ReferenceQuery(ReferenceQuery(operator='match', fulltext='b'), operator='not'), operator='and'), operator='and'), + self.catalog(ReferenceQuery(ReferenceQuery(ReferenceQuery(operator='mroonga', fulltext='a'), + ReferenceQuery(ReferenceQuery(operator='mroonga', fulltext='b'), operator='not'), operator='and'), operator='and'), {'fulltext': 'a AND NOT b'}) def test_006_testRelatedKey_with_multiple_join(self): @@ -540,7 +544,7 @@ class TestSQLCatalog(ERP5TypeTestCase): check_search_text=False) def test_009_testFullTextKey(self): - self.catalog(ReferenceQuery(ReferenceQuery(operator='match', fulltext='a'), operator='and'), + self.catalog(ReferenceQuery(ReferenceQuery(operator='mroonga', fulltext='a'), operator='and'), {'fulltext': 'a'}) def test_isAdvancedSearchText(self): @@ -551,15 +555,20 @@ class TestSQLCatalog(ERP5TypeTestCase): def test_FullTextSearchMergesQueries(self): """ + XXX this test is for old FullTextKey, not for MroongaFullTextKey + that merges queries only when logical_operator is 'and'. Also + _renderValueAsSearchText it not perfect so that we cannot use the + test codes below for mroonga search key. + FullText criterion on the same scope must be merged into one query. Logical operator is ignored, as fulltext operators are expected instead. """ - self.catalog(ReferenceQuery(ReferenceQuery(operator='match', fulltext='a b'), operator='and'), - {'fulltext': 'a AND b'}) - self.catalog(ReferenceQuery(ReferenceQuery(operator='match', fulltext='a b'), operator='and'), - {'fulltext': 'a OR b'}) - self.catalog(ReferenceQuery(ReferenceQuery(ReferenceQuery(operator='match', fulltext='a b'), operator='not'), operator='and'), - {'fulltext': 'NOT (a b)'}) + self.catalog(ReferenceQuery(ReferenceQuery(operator='match', old_fulltext='a b'), operator='and'), + {'old_fulltext': 'a AND b'}) + self.catalog(ReferenceQuery(ReferenceQuery(operator='match', old_fulltext='a b'), operator='and'), + {'old_fulltext': 'a OR b'}) + self.catalog(ReferenceQuery(ReferenceQuery(ReferenceQuery(operator='match', old_fulltext='a b'), operator='not'), operator='and'), + {'old_fulltext': 'NOT (a b)'}) def test_NoneValueToSimpleQuery(self): """ @@ -583,60 +592,69 @@ class TestSQLCatalog(ERP5TypeTestCase): def test_FullTextBooleanMode(self): """ + XXX this test is for old FullTextKey, not for MroongaFullTextKey + that does no automatic mode switch. + Fulltext searches must switch automatically to boolean mode if boolean operators are found in search value. """ self.catalog(ReferenceQuery(ReferenceQuery(operator='match_boolean', - fulltext=MatchList(['a*'])), operator='and'), - {'fulltext': 'a*'}) + old_fulltext=MatchList(['a*'])), operator='and'), + {'old_fulltext': 'a*'}) self.catalog(ReferenceQuery(ReferenceQuery(operator='match_boolean', - fulltext=MatchList(['a* b'])), operator='and'), - {'fulltext': 'a* b'}) + old_fulltext=MatchList(['a* b'])), operator='and'), + {'old_fulltext': 'a* b'}) - self.catalog(ReferenceQuery(ReferenceQuery(operator='match', fulltext='*a'), + self.catalog(ReferenceQuery(ReferenceQuery(operator='match', old_fulltext='*a'), operator='and'), - {'fulltext': '*a'}) + {'old_fulltext': '*a'}) - self.catalog(ReferenceQuery(ReferenceQuery(operator='match', fulltext='a'), + self.catalog(ReferenceQuery(ReferenceQuery(operator='match', old_fulltext='a'), operator='and'), - {'fulltext': 'a'}) + {'old_fulltext': 'a'}) - self.catalog(ReferenceQuery(ReferenceQuery(operator='match', fulltext='a+b'), operator='and'), - {'fulltext': 'a+b'}) + self.catalog(ReferenceQuery(ReferenceQuery(operator='match', old_fulltext='a+b'), operator='and'), + {'old_fulltext': 'a+b'}) self.catalog(ReferenceQuery(ReferenceQuery(operator='match_boolean', - fulltext=MatchList(['a +b', '+b a'])), operator='and'), - {'fulltext': 'a +b'}, check_search_text=False) + old_fulltext=MatchList(['a +b', '+b a'])), operator='and'), + {'old_fulltext': 'a +b'}, check_search_text=False) self.catalog(ReferenceQuery(ReferenceQuery( ReferenceQuery(operator='=', uid='foo'), ReferenceQuery(operator='match_boolean', - fulltext=MatchList(['+a b', 'b +a'])), - operator='and'), operator='and'), {'fulltext': '+a b uid:foo'}) + old_fulltext=MatchList(['+a b', 'b +a'])), + operator='and'), operator='and'), {'old_fulltext': '+a b uid:foo'}) def test_FullTextQuoting(self): + """ + XXX this test is for old FullTextKey, not for MroongaFullTextKey + that merges queries only when logical_operator is 'and'. Also + _renderValueAsSearchText it not perfect so that we cannot use the + test codes below for mroonga search key. + """ # Quotes must be kept self.catalog(ReferenceQuery(ReferenceQuery(operator='match', - fulltext='"a"'), operator='and'), - {'fulltext': '"a"'}) + old_fulltext='"a"'), operator='and'), + {'old_fulltext': '"a"'}) self.catalog(ReferenceQuery(ReferenceQuery(operator='match', - fulltext='"foo" bar "baz"'), operator='and'), - {'fulltext': '"foo" bar "baz"'}) + old_fulltext='"foo" bar "baz"'), operator='and'), + {'old_fulltext': '"foo" bar "baz"'}) # ...But each column must follow rules defined in configured SearchKey for # that column (in this case: quotes must be stripped). ref_query = ReferenceQuery(ReferenceQuery(ReferenceQuery(operator='match', - fulltext='"foo" bar'), ReferenceQuery(operator='=', + old_fulltext='"foo" bar'), ReferenceQuery(operator='=', default='hoge \"pon'), operator='and'), operator='and') self.catalog(ref_query, { - 'keyword': 'default:"hoge \\"pon" AND fulltext:("foo" bar)'}) + 'keyword': 'default:"hoge \\"pon" AND old_fulltext:("foo" AND bar)'}) self.catalog(ref_query, { - 'fulltext': '"foo" bar AND default:"hoge \\"pon"'}) + 'old_fulltext': '"foo" bar AND default:"hoge \\"pon"'}) ref_query = ReferenceQuery(ReferenceQuery(ReferenceQuery(operator='match', - fulltext='"\\"foo\\" bar"'), ReferenceQuery(operator='=', + old_fulltext='"\\"foo\\" bar"'), ReferenceQuery(operator='=', default='hoge \"pon'), operator='and'), operator='and') self.catalog(ref_query, { - 'keyword': 'default:"hoge \\"pon" AND fulltext:"\\"foo\\" bar"'}) + 'keyword': 'default:"hoge \\"pon" AND old_fulltext:"\\"foo\\" bar"'}) def test_DefaultKeyTextRendering(self): self.catalog(ReferenceQuery(ReferenceQuery(operator='like', default='a% b'), operator='and'), -- 2.30.9