From 4f133d81d7a604976589e3e09c31c6f7c1126a4b Mon Sep 17 00:00:00 2001
From: Kazuhiko SHIOZAKI <kazuhiko@nexedi.com>
Date: Mon, 7 Oct 2024 22:07:19 +0200
Subject: [PATCH] ERP5Site: force READ-COMMITTED isolation for
 cmf_activity_sql_connection.

---
 product/ERP5/ERP5Site.py                   |  6 ++++--
 product/ERP5Type/tests/ERP5TypeTestCase.py | 19 ++++++++++++-------
 product/ERP5Type/tests/runUnitTest.py      |  2 +-
 3 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/product/ERP5/ERP5Site.py b/product/ERP5/ERP5Site.py
index feccf421a1f..d4e292f5077 100644
--- a/product/ERP5/ERP5Site.py
+++ b/product/ERP5/ERP5Site.py
@@ -50,6 +50,7 @@ from Products.ERP5Type.mixin.response_header_generator import ResponseHeaderGene
 from zLOG import LOG, INFO, WARNING, ERROR
 from zExceptions import BadRequest
 import os
+import re
 import warnings
 import transaction
 from App.config import getConfiguration
@@ -84,7 +85,7 @@ def manage_addERP5Site(self,
                        validate_email=0,
                        erp5_catalog_storage='erp5_mysql_innodb_catalog',
                        erp5_sql_connection_string=default_sql_connection_string,
-                       cmf_activity_sql_connection_string=default_sql_connection_string,
+                       cmf_activity_sql_connection_string='!READ-COMMITTED %s' % default_sql_connection_string,
                        bt5_repository_url='',
                        bt5='',
                        id_store_interval='',
@@ -2281,7 +2282,8 @@ class ERP5Generator(PortalGenerator):
       # The only difference compared to activity connection is the
       # minus prepended to the connection string.
       if id == 'erp5_sql_transactionless_connection':
-        connection_string = '-' + p.cmf_activity_sql_connection_string
+        # omit isolation-level and add '-' sign in front of the database.
+        connection_string = re.sub(r'((?:[%*][^ ]+ )*)(![^ ]+ )?(.+)', r'\1-\3', p.cmf_activity_sql_connection_string)
       else:
         connection_string = getattr(p, id + '_string')
       manage_add(id, title, connection_string, **kw)
diff --git a/product/ERP5Type/tests/ERP5TypeTestCase.py b/product/ERP5Type/tests/ERP5TypeTestCase.py
index 724356b4408..27560d2cc1b 100644
--- a/product/ERP5Type/tests/ERP5TypeTestCase.py
+++ b/product/ERP5Type/tests/ERP5TypeTestCase.py
@@ -102,17 +102,22 @@ def _getConnectionStringDict():
   connection_string_dict = {}
   default = os.environ.get('erp5_sql_connection_string')
   for connection in ('erp5_sql_connection_string',
-                     'erp5_sql_deferred_connection_string',
-                     # default value for transactionless is derived from value
-                     # for cmf_activity, so process it last
-                     'cmf_activity_sql_connection_string'):
+                     'erp5_sql_deferred_connection_string'):
     connection_string = os.environ.get(connection, default)
     if connection_string:
       connection_string_dict[connection] = connection_string
+  connection = 'cmf_activity_sql_connection_string'
+  # force READ-COMMITTED isolation-level.
+  connection_string_dict[connection] = \
+    os.environ.get(connection, re.sub(
+      r'((?:[%*][^ ]+ )*)(![^ ]+ )?(.+)', r'\1!READ-COMMITTED \3', connection_string_dict['erp5_sql_connection_string']))
+  # default value for transactionless is derived from value
+  # for cmf_activity, so process it last
   connection = 'erp5_sql_transactionless_connection_string'
-  if os.environ.get(connection, connection_string):
-    connection_string_dict[connection] = \
-      os.environ.get(connection, '-' + connection_string)
+  # omit isolation-level and add '-' sign in front of the database.
+  connection_string_dict[connection] = \
+    os.environ.get(connection, re.sub(
+      r'((?:[%*][^ ]+ )*)(![^ ]+ )?(.+)', r'\1-\3', connection_string_dict['cmf_activity_sql_connection_string']))
   return connection_string_dict
 
 def _getConversionServerUrlList():
diff --git a/product/ERP5Type/tests/runUnitTest.py b/product/ERP5Type/tests/runUnitTest.py
index 8e93a321b3a..525ad3dc69a 100755
--- a/product/ERP5Type/tests/runUnitTest.py
+++ b/product/ERP5Type/tests/runUnitTest.py
@@ -65,7 +65,7 @@ Options:
   --cmf_activity_sql_connection_string=STRING
                              ZSQL Connection string for
                              cmf_activity_sql_connection (if unset, defaults to
-                             erp5_sql_connection_string)
+                             erp5_sql_connection_string with "!READ-COMMITTED")
   --extra_sql_connection_string_list=STRING
                              Used when 2 or more ZSQL connection strings are
                              needed. By defaut, it will take the last four
-- 
2.30.9