3333#define HAVE_TRACE_V2
3434#endif
3535
36+ static const char *
37+ get_isolation_level (const char * level )
38+ {
39+ assert (level != NULL );
40+ static const char * const allowed_levels [] = {
41+ "" ,
42+ "DEFERRED" ,
43+ "IMMEDIATE" ,
44+ "EXCLUSIVE" ,
45+ NULL
46+ };
47+ for (int i = 0 ; allowed_levels [i ] != NULL ; i ++ ) {
48+ const char * candidate = allowed_levels [i ];
49+ if (sqlite3_stricmp (level , candidate ) == 0 ) {
50+ return candidate ;
51+ }
52+ }
53+ PyErr_SetString (PyExc_ValueError ,
54+ "isolation_level string must be '', 'DEFERRED', "
55+ "'IMMEDIATE', or 'EXCLUSIVE'" );
56+ return NULL ;
57+ }
58+
59+ static int
60+ isolation_level_converter (PyObject * str_or_none , const char * * result )
61+ {
62+ if (Py_IsNone (str_or_none )) {
63+ * result = NULL ;
64+ }
65+ else if (PyUnicode_Check (str_or_none )) {
66+ Py_ssize_t sz ;
67+ const char * str = PyUnicode_AsUTF8AndSize (str_or_none , & sz );
68+ if (str == NULL ) {
69+ return 0 ;
70+ }
71+ if (strlen (str ) != (size_t )sz ) {
72+ PyErr_SetString (PyExc_ValueError , "embedded null character" );
73+ return 0 ;
74+ }
75+
76+ const char * level = get_isolation_level (str );
77+ if (level == NULL ) {
78+ return 0 ;
79+ }
80+ * result = level ;
81+ }
82+ else {
83+ PyErr_SetString (PyExc_TypeError ,
84+ "isolation_level must be str or None" );
85+ return 0 ;
86+ }
87+ return 1 ;
88+ }
89+
3690static int
3791clinic_fsconverter (PyObject * pathlike , const char * * result )
3892{
@@ -100,29 +154,6 @@ new_statement_cache(pysqlite_Connection *self, pysqlite_state *state,
100154 return res ;
101155}
102156
103- static const char *
104- get_isolation_level (const char * level )
105- {
106- assert (level != NULL );
107- static const char * const allowed_levels [] = {
108- "" ,
109- "DEFERRED" ,
110- "IMMEDIATE" ,
111- "EXCLUSIVE" ,
112- NULL
113- };
114- for (int i = 0 ; allowed_levels [i ] != NULL ; i ++ ) {
115- const char * candidate = allowed_levels [i ];
116- if (sqlite3_stricmp (level , candidate ) == 0 ) {
117- return candidate ;
118- }
119- }
120- PyErr_SetString (PyExc_ValueError ,
121- "isolation_level string must be '', 'DEFERRED', "
122- "'IMMEDIATE', or 'EXCLUSIVE'" );
123- return NULL ;
124- }
125-
126157/*[python input]
127158class FSConverter_converter(CConverter):
128159 type = "const char *"
@@ -131,16 +162,21 @@ class FSConverter_converter(CConverter):
131162 self.c_default = "NULL"
132163 def cleanup(self):
133164 return f"PyMem_Free((void *){self.name});\n"
165+
166+ class IsolationLevel_converter(CConverter):
167+ type = "const char *"
168+ converter = "isolation_level_converter"
169+
134170[python start generated code]*/
135- /*[python end generated code: output=da39a3ee5e6b4b0d input=7b3be538bc4058c0 ]*/
171+ /*[python end generated code: output=da39a3ee5e6b4b0d input=be142323885672ab ]*/
136172
137173/*[clinic input]
138174_sqlite3.Connection.__init__ as pysqlite_connection_init
139175
140176 database: FSConverter
141177 timeout: double = 5.0
142178 detect_types: int = 0
143- isolation_level: str(accept={str, NoneType}) = ""
179+ isolation_level: IsolationLevel = ""
144180 check_same_thread: bool(accept={int}) = True
145181 factory: object(c_default='(PyObject*)clinic_state()->ConnectionType') = ConnectionType
146182 cached_statements as cache_size: int = 128
@@ -153,7 +189,7 @@ pysqlite_connection_init_impl(pysqlite_Connection *self,
153189 int detect_types , const char * isolation_level ,
154190 int check_same_thread , PyObject * factory ,
155191 int cache_size , int uri )
156- /*[clinic end generated code: output=7d640ae1d83abfd4 input=35e316f66d9f70fd ]*/
192+ /*[clinic end generated code: output=7d640ae1d83abfd4 input=342173993434ba1e ]*/
157193{
158194 if (PySys_Audit ("sqlite3.connect" , "s" , database ) < 0 ) {
159195 return -1 ;
@@ -189,15 +225,6 @@ pysqlite_connection_init_impl(pysqlite_Connection *self,
189225 return -1 ;
190226 }
191227
192- // Convert isolation level to begin statement.
193- const char * level = NULL ;
194- if (isolation_level != NULL ) {
195- level = get_isolation_level (isolation_level );
196- if (level == NULL ) {
197- return -1 ;
198- }
199- }
200-
201228 // Create LRU statement cache; returns a new reference.
202229 PyObject * statement_cache = new_statement_cache (self , state , cache_size );
203230 if (statement_cache == NULL ) {
@@ -215,7 +242,7 @@ pysqlite_connection_init_impl(pysqlite_Connection *self,
215242 self -> db = db ;
216243 self -> state = state ;
217244 self -> detect_types = detect_types ;
218- self -> isolation_level = level ;
245+ self -> isolation_level = isolation_level ;
219246 self -> check_same_thread = check_same_thread ;
220247 self -> thread_ident = PyThread_get_thread_ident ();
221248 self -> statement_cache = statement_cache ;
@@ -1375,26 +1402,9 @@ pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* iso
13751402 return -1 ;
13761403 }
13771404 Py_DECREF (res );
1405+ return 0 ;
13781406 }
1379- else if (PyUnicode_Check (isolation_level )) {
1380- Py_ssize_t len ;
1381- const char * cstr_level = PyUnicode_AsUTF8AndSize (isolation_level , & len );
1382- if (cstr_level == NULL ) {
1383- return -1 ;
1384- }
1385- if (strlen (cstr_level ) != (size_t )len ) {
1386- PyErr_SetString (PyExc_ValueError , "embedded null character" );
1387- return -1 ;
1388- }
1389- const char * level = get_isolation_level (cstr_level );
1390- if (level == NULL ) {
1391- return -1 ;
1392- }
1393- self -> isolation_level = level ;
1394- }
1395- else {
1396- PyErr_SetString (PyExc_TypeError ,
1397- "isolation_level must be str or None" );
1407+ if (!isolation_level_converter (isolation_level , & self -> isolation_level )) {
13981408 return -1 ;
13991409 }
14001410 return 0 ;
0 commit comments