@@ -180,7 +180,6 @@ class User(Base):
180180""" # noqa E501
181181import datetime
182182import re
183- import warnings
184183
185184from collections import defaultdict
186185
@@ -947,71 +946,29 @@ def get_isolation_level_values(self, dbapi_conn):
947946 # Methods merged from PyODBCConnector
948947
949948 def get_isolation_level (self , dbapi_conn ):
950- # Return the stored isolation level. IBM i ODBC doesn't support
951- # querying isolation level from an active connection.
949+ # Return the stored isolation level. pyodbc doesn't provide a way to
950+ # get attributes, only set them
952951 return self .isolation_level
953952
954953 def set_isolation_level (self , connection , level ):
955954 """Set the isolation level for this connection.
956955
957956 This method attempts to set the isolation level using ODBC attributes.
958957 Due to IBM i ODBC driver limitations, this may fail with error HY011 if
959- called on an active connection or during a transaction. The isolation level
960- will still be validated and stored for reference.
961-
962- For guaranteed isolation level setting, use the commit_mode connection parameter:
963- commit_mode=0 -> *CHG (READ UNCOMMITTED)
964- commit_mode=1 -> *CS (READ COMMITTED) - default
965- commit_mode=2 -> *ALL (REPEATABLE READ)
966- commit_mode=3 -> *NONE (no transactions)
967-
968- Example:
969- engine = create_engine("ibmi+pyodbc://user:pass@host/db?commit_mode=1")
958+ called during a transaction.
970959 """
971- if level is None :
972- level = self .default_isolation_level
973- level = str (level ).replace ("_" , " " )
974- if level not in self ._isolation_lookup :
960+ self .isolation_level = level
961+ level = level .replace ("_" , " " )
962+ if level in self ._isolation_lookup :
963+ connection .set_attr (
964+ self .dbapi .SQL_ATTR_TXN_ISOLATION , self ._isolation_lookup [level ]
965+ )
966+ else :
975967 raise exc .ArgumentError (
976968 "Invalid value '%s' for isolation_level. "
977969 "Valid isolation levels for %s are %s"
978970 % (level , self .name , ", " .join (self ._isolation_lookup .keys ()))
979971 )
980-
981- # Try to set via ODBC attribute
982- # This should work when called during on_connect(), but may fail with HY011
983- # if called on an active connection or during a transaction
984- try :
985- connection .set_attr (
986- self .dbapi .SQL_ATTR_TXN_ISOLATION ,
987- self ._isolation_lookup [level ]
988- )
989- except Exception as e :
990- error_msg = str (e )
991-
992- # HY011 (Operation invalid at this time) is expected when connection is active
993- if "HY011" in error_msg or "30033" in error_msg :
994- warnings .warn (
995- f"IBM i ODBC driver returned HY011 when setting isolation level to '{ level } '. "
996- "This is expected when called on an active connection. "
997- "Isolation level stored but not applied via ODBC. "
998- "To guarantee isolation level is set, use connection string "
999- "parameter commit_mode (e.g., commit_mode=1 for READ COMMITTED)." ,
1000- UserWarning ,
1001- stacklevel = 2
1002- )
1003- else :
1004- # Unexpected error - may indicate a real problem
1005- warnings .warn (
1006- f"Failed to set isolation level via ODBC: { e } . "
1007- "Isolation level will be stored but may not be active. "
1008- "To ensure isolation level is set, use connection string "
1009- "parameter commit_mode (e.g., commit_mode=1 for READ COMMITTED)." ,
1010- UserWarning ,
1011- stacklevel = 2
1012- )
1013-
1014- self .isolation_level = level
1015972
1016973 def reset_isolation_level (self , connection ):
1017974 self .set_isolation_level (connection , self .default_isolation_level )
@@ -1041,7 +998,6 @@ def dbapi(cls):
1041998 "use_system_naming" : ("NAM" , to_bool , False ),
1042999 "trim_char_fields" : ("TRIMCHAR" , to_bool , None ),
10431000 "lob_threshold_kb" : ("MAXFIELDLEN" , int , None ),
1044- "commit_mode" : ("CMT" , int , None ), # 0=*CHG, 1=*CS, 2=*ALL, 3=*NONE
10451001 }
10461002
10471003 DRIVER_KEYWORDS_SPECIAL = {
0 commit comments