Mercurial > p > mysql-python > mysqldb-2
comparison src/mysqlmod.c @ 55:e606fd52e866 MySQLdb
make things a little cleaner by moving to a src directory for the C code
author | kylev |
---|---|
date | Fri, 27 Feb 2009 19:14:09 +0000 |
parents | _mysql.c@e80676c3505f |
children | 98d968f5af11 |
comparison
equal
deleted
inserted
replaced
54:6e31278d3433 | 55:e606fd52e866 |
---|---|
1 /* -*- mode: C; indent-tabs-mode: t; c-basic-offset: 8; -*- */ | |
2 | |
3 #include "mysqlmod.h" | |
4 | |
5 PyObject *_mysql_MySQLError; | |
6 PyObject *_mysql_Warning; | |
7 PyObject *_mysql_Error; | |
8 PyObject *_mysql_DatabaseError; | |
9 PyObject *_mysql_InterfaceError; | |
10 PyObject *_mysql_DataError; | |
11 PyObject *_mysql_OperationalError; | |
12 PyObject *_mysql_IntegrityError; | |
13 PyObject *_mysql_InternalError; | |
14 PyObject *_mysql_ProgrammingError; | |
15 PyObject *_mysql_NotSupportedError; | |
16 PyObject *_mysql_error_map; | |
17 | |
18 int _mysql_server_init_done = 0; | |
19 | |
20 PyObject * | |
21 _mysql_Exception(_mysql_ConnectionObject *c) | |
22 { | |
23 PyObject *t, *e; | |
24 int merr; | |
25 | |
26 if (!(t = PyTuple_New(2))) return NULL; | |
27 if (!_mysql_server_init_done) { | |
28 e = _mysql_InternalError; | |
29 PyTuple_SET_ITEM(t, 0, PyInt_FromLong(-1L)); | |
30 PyTuple_SET_ITEM(t, 1, PyString_FromString("server not initialized")); | |
31 PyErr_SetObject(e, t); | |
32 Py_DECREF(t); | |
33 return NULL; | |
34 } | |
35 merr = mysql_errno(&(c->connection)); | |
36 if (!merr) | |
37 e = _mysql_InterfaceError; | |
38 else if (merr > CR_MAX_ERROR) { | |
39 PyTuple_SET_ITEM(t, 0, PyInt_FromLong(-1L)); | |
40 PyTuple_SET_ITEM(t, 1, PyString_FromString("error totally whack")); | |
41 PyErr_SetObject(_mysql_InterfaceError, t); | |
42 Py_DECREF(t); | |
43 return NULL; | |
44 } | |
45 else { | |
46 PyObject *py_merr = PyInt_FromLong(merr); | |
47 e = PyDict_GetItem(_mysql_error_map, py_merr); | |
48 Py_DECREF(py_merr); | |
49 if (!e) { | |
50 if (merr < 1000) e = _mysql_InternalError; | |
51 else e = _mysql_OperationalError; | |
52 } | |
53 } | |
54 PyTuple_SET_ITEM(t, 0, PyInt_FromLong((long)merr)); | |
55 PyTuple_SET_ITEM(t, 1, PyString_FromString(mysql_error(&(c->connection)))); | |
56 PyErr_SetObject(e, t); | |
57 Py_DECREF(t); | |
58 return NULL; | |
59 } | |
60 | |
61 static char _mysql_server_init__doc__[] = | |
62 "Initialize embedded server. If this client is not linked against\n\ | |
63 the embedded server library, this function does nothing.\n\ | |
64 \n\ | |
65 args -- sequence of command-line arguments\n\ | |
66 groups -- sequence of groups to use in defaults files\n\ | |
67 "; | |
68 | |
69 static PyObject *_mysql_server_init( | |
70 PyObject *self, | |
71 PyObject *args, | |
72 PyObject *kwargs) { | |
73 static char *kwlist[] = {"args", "groups", NULL}; | |
74 char **cmd_args_c=NULL, **groups_c=NULL, *s; | |
75 Py_ssize_t cmd_argc=0, i, groupc; | |
76 PyObject *cmd_args=NULL, *groups=NULL, *ret=NULL, *item; | |
77 | |
78 if (_mysql_server_init_done) { | |
79 PyErr_SetString(_mysql_ProgrammingError, | |
80 "already initialized"); | |
81 return NULL; | |
82 } | |
83 | |
84 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO", kwlist, | |
85 &cmd_args, &groups)) | |
86 return NULL; | |
87 | |
88 #if MYSQL_VERSION_ID >= 40000 | |
89 if (cmd_args) { | |
90 if (!PySequence_Check(cmd_args)) { | |
91 PyErr_SetString(PyExc_TypeError, | |
92 "args must be a sequence"); | |
93 goto finish; | |
94 } | |
95 cmd_argc = PySequence_Size(cmd_args); | |
96 if (cmd_argc == -1) { | |
97 PyErr_SetString(PyExc_TypeError, | |
98 "args could not be sized"); | |
99 goto finish; | |
100 } | |
101 cmd_args_c = (char **) PyMem_Malloc(cmd_argc*sizeof(char *)); | |
102 for (i=0; i< cmd_argc; i++) { | |
103 item = PySequence_GetItem(cmd_args, i); | |
104 s = PyString_AsString(item); | |
105 Py_DECREF(item); | |
106 if (!s) { | |
107 PyErr_SetString(PyExc_TypeError, | |
108 "args must contain strings"); | |
109 goto finish; | |
110 } | |
111 cmd_args_c[i] = s; | |
112 } | |
113 } | |
114 if (groups) { | |
115 if (!PySequence_Check(groups)) { | |
116 PyErr_SetString(PyExc_TypeError, | |
117 "groups must be a sequence"); | |
118 goto finish; | |
119 } | |
120 groupc = PySequence_Size(groups); | |
121 if (groupc == -1) { | |
122 PyErr_SetString(PyExc_TypeError, | |
123 "groups could not be sized"); | |
124 goto finish; | |
125 } | |
126 groups_c = (char **) PyMem_Malloc((1+groupc)*sizeof(char *)); | |
127 for (i=0; i< groupc; i++) { | |
128 item = PySequence_GetItem(groups, i); | |
129 s = PyString_AsString(item); | |
130 Py_DECREF(item); | |
131 if (!s) { | |
132 PyErr_SetString(PyExc_TypeError, | |
133 "groups must contain strings"); | |
134 goto finish; | |
135 } | |
136 groups_c[i] = s; | |
137 } | |
138 groups_c[groupc] = (char *)NULL; | |
139 } | |
140 /* even though this may block, don't give up the interpreter lock | |
141 so that the server can't be initialized multiple times. */ | |
142 if (mysql_server_init(cmd_argc, cmd_args_c, groups_c)) { | |
143 _mysql_Exception(NULL); | |
144 goto finish; | |
145 } | |
146 #endif | |
147 ret = Py_None; | |
148 Py_INCREF(Py_None); | |
149 _mysql_server_init_done = 1; | |
150 finish: | |
151 PyMem_Free(groups_c); | |
152 PyMem_Free(cmd_args_c); | |
153 return ret; | |
154 } | |
155 | |
156 static char _mysql_server_end__doc__[] = | |
157 "Shut down embedded server. If not using an embedded server, this\n\ | |
158 does nothing."; | |
159 | |
160 static PyObject *_mysql_server_end( | |
161 PyObject *self, | |
162 PyObject *unused) { | |
163 if (_mysql_server_init_done) { | |
164 #if MYSQL_VERSION_ID >= 40000 | |
165 mysql_server_end(); | |
166 #endif | |
167 _mysql_server_init_done = 0; | |
168 Py_INCREF(Py_None); | |
169 return Py_None; | |
170 } | |
171 return _mysql_Exception(NULL); | |
172 } | |
173 | |
174 #if MYSQL_VERSION_ID >= 32314 | |
175 static char _mysql_thread_safe__doc__[] = | |
176 "Indicates whether the client is compiled as thread-safe."; | |
177 | |
178 static PyObject *_mysql_thread_safe( | |
179 PyObject *self, | |
180 PyObject *unused) { | |
181 | |
182 check_server_init(NULL); | |
183 return PyInt_FromLong((long)mysql_thread_safe()); | |
184 } | |
185 #endif | |
186 | |
187 extern char _mysql_connect__doc__[]; | |
188 PyObject * | |
189 _mysql_connect( | |
190 PyObject *self, | |
191 PyObject *args, | |
192 PyObject *kwargs); | |
193 | |
194 static char _mysql_debug__doc__[] = | |
195 "Does a DBUG_PUSH with the given string.\n\ | |
196 mysql_debug() uses the Fred Fish debug library.\n\ | |
197 To use this function, you must compile the client library to\n\ | |
198 support debugging.\n\ | |
199 "; | |
200 static PyObject * | |
201 _mysql_debug( | |
202 PyObject *self, | |
203 PyObject *args) | |
204 { | |
205 char *debug; | |
206 if (!PyArg_ParseTuple(args, "s", &debug)) return NULL; | |
207 mysql_debug(debug); | |
208 Py_INCREF(Py_None); | |
209 return Py_None; | |
210 } | |
211 | |
212 extern char _mysql_escape_string__doc__[]; | |
213 PyObject * | |
214 _mysql_escape_string( | |
215 _mysql_ConnectionObject *self, | |
216 PyObject *args); | |
217 | |
218 extern char _mysql_string_literal__doc__[]; | |
219 PyObject * | |
220 _mysql_string_literal( | |
221 _mysql_ConnectionObject *self, | |
222 PyObject *args); | |
223 | |
224 static PyObject *_mysql_NULL; | |
225 | |
226 PyObject * | |
227 _escape_item( | |
228 PyObject *item, | |
229 PyObject *d) | |
230 { | |
231 PyObject *quoted=NULL, *itemtype, *itemconv; | |
232 if (!(itemtype = PyObject_Type(item))) | |
233 goto error; | |
234 itemconv = PyObject_GetItem(d, itemtype); | |
235 Py_DECREF(itemtype); | |
236 if (!itemconv) { | |
237 PyErr_Clear(); | |
238 itemconv = PyObject_GetItem(d, | |
239 (PyObject *) &PyString_Type); | |
240 } | |
241 if (!itemconv) { | |
242 PyErr_SetString(PyExc_TypeError, | |
243 "no default type converter defined"); | |
244 goto error; | |
245 } | |
246 quoted = PyObject_CallFunction(itemconv, "OO", item, d); | |
247 Py_DECREF(itemconv); | |
248 error: | |
249 return quoted; | |
250 } | |
251 | |
252 extern char _mysql_escape__doc__[]; | |
253 PyObject * | |
254 _mysql_escape( | |
255 PyObject *self, | |
256 PyObject *args); | |
257 | |
258 static char _mysql_escape_sequence__doc__[] = | |
259 "escape_sequence(seq, dict) -- escape any special characters in sequence\n\ | |
260 seq using mapping dict to provide quoting functions for each type.\n\ | |
261 Returns a tuple of escaped items."; | |
262 static PyObject * | |
263 _mysql_escape_sequence( | |
264 PyObject *self, | |
265 PyObject *args) | |
266 { | |
267 PyObject *o=NULL, *d=NULL, *r=NULL, *item, *quoted; | |
268 int i, n; | |
269 if (!PyArg_ParseTuple(args, "OO:escape_sequence", &o, &d)) | |
270 goto error; | |
271 if (!PyMapping_Check(d)) { | |
272 PyErr_SetString(PyExc_TypeError, | |
273 "argument 2 must be a mapping"); | |
274 return NULL; | |
275 } | |
276 if ((n = PyObject_Length(o)) == -1) goto error; | |
277 if (!(r = PyTuple_New(n))) goto error; | |
278 for (i=0; i<n; i++) { | |
279 item = PySequence_GetItem(o, i); | |
280 if (!item) goto error; | |
281 quoted = _escape_item(item, d); | |
282 Py_DECREF(item); | |
283 if (!quoted) goto error; | |
284 PyTuple_SET_ITEM(r, i, quoted); | |
285 } | |
286 return r; | |
287 error: | |
288 Py_XDECREF(r); | |
289 return NULL; | |
290 } | |
291 | |
292 static char _mysql_escape_dict__doc__[] = | |
293 "escape_sequence(d, dict) -- escape any special characters in\n\ | |
294 dictionary d using mapping dict to provide quoting functions for each type.\n\ | |
295 Returns a dictionary of escaped items."; | |
296 static PyObject * | |
297 _mysql_escape_dict( | |
298 PyObject *self, | |
299 PyObject *args) | |
300 { | |
301 PyObject *o=NULL, *d=NULL, *r=NULL, *item, *quoted, *pkey; | |
302 Py_ssize_t ppos = 0; | |
303 if (!PyArg_ParseTuple(args, "O!O:escape_dict", &PyDict_Type, &o, &d)) | |
304 goto error; | |
305 if (!PyMapping_Check(d)) { | |
306 PyErr_SetString(PyExc_TypeError, | |
307 "argument 2 must be a mapping"); | |
308 return NULL; | |
309 } | |
310 if (!(r = PyDict_New())) goto error; | |
311 while (PyDict_Next(o, &ppos, &pkey, &item)) { | |
312 quoted = _escape_item(item, d); | |
313 if (!quoted) goto error; | |
314 if (PyDict_SetItem(r, pkey, quoted)==-1) goto error; | |
315 Py_DECREF(quoted); | |
316 } | |
317 return r; | |
318 error: | |
319 Py_XDECREF(r); | |
320 return NULL; | |
321 } | |
322 | |
323 static char _mysql_get_client_info__doc__[] = | |
324 "get_client_info() -- Returns a string that represents\n\ | |
325 the client library version."; | |
326 static PyObject * | |
327 _mysql_get_client_info( | |
328 PyObject *self, | |
329 PyObject *unused) | |
330 { | |
331 check_server_init(NULL); | |
332 return PyString_FromString(mysql_get_client_info()); | |
333 } | |
334 | |
335 extern PyTypeObject _mysql_ConnectionObject_Type; | |
336 extern PyTypeObject _mysql_ResultObject_Type; | |
337 | |
338 static PyMethodDef | |
339 _mysql_methods[] = { | |
340 { | |
341 "connect", | |
342 (PyCFunction)_mysql_connect, | |
343 METH_VARARGS | METH_KEYWORDS, | |
344 _mysql_connect__doc__ | |
345 }, | |
346 { | |
347 "debug", | |
348 (PyCFunction)_mysql_debug, | |
349 METH_VARARGS, | |
350 _mysql_debug__doc__ | |
351 }, | |
352 { | |
353 "escape", | |
354 (PyCFunction)_mysql_escape, | |
355 METH_VARARGS, | |
356 _mysql_escape__doc__ | |
357 }, | |
358 { | |
359 "escape_sequence", | |
360 (PyCFunction)_mysql_escape_sequence, | |
361 METH_VARARGS, | |
362 _mysql_escape_sequence__doc__ | |
363 }, | |
364 { | |
365 "escape_dict", | |
366 (PyCFunction)_mysql_escape_dict, | |
367 METH_VARARGS, | |
368 _mysql_escape_dict__doc__ | |
369 }, | |
370 { | |
371 "escape_string", | |
372 (PyCFunction)_mysql_escape_string, | |
373 METH_VARARGS, | |
374 _mysql_escape_string__doc__ | |
375 }, | |
376 { | |
377 "string_literal", | |
378 (PyCFunction)_mysql_string_literal, | |
379 METH_VARARGS, | |
380 _mysql_string_literal__doc__ | |
381 }, | |
382 { | |
383 "get_client_info", | |
384 (PyCFunction)_mysql_get_client_info, | |
385 METH_NOARGS, | |
386 _mysql_get_client_info__doc__ | |
387 }, | |
388 #if MYSQL_VERSION_ID >= 32314 | |
389 { | |
390 "thread_safe", | |
391 (PyCFunction)_mysql_thread_safe, | |
392 METH_NOARGS, | |
393 _mysql_thread_safe__doc__ | |
394 }, | |
395 #endif | |
396 { | |
397 "server_init", | |
398 (PyCFunction)_mysql_server_init, | |
399 METH_VARARGS | METH_KEYWORDS, | |
400 _mysql_server_init__doc__ | |
401 }, | |
402 { | |
403 "server_end", | |
404 (PyCFunction)_mysql_server_end, | |
405 METH_NOARGS, | |
406 _mysql_server_end__doc__ | |
407 }, | |
408 {NULL, NULL} /* sentinel */ | |
409 }; | |
410 | |
411 static PyObject * | |
412 _mysql_NewException( | |
413 PyObject *dict, | |
414 PyObject *edict, | |
415 char *name) | |
416 { | |
417 PyObject *e; | |
418 | |
419 if (!(e = PyDict_GetItemString(edict, name))) | |
420 return NULL; | |
421 if (PyDict_SetItemString(dict, name, e)) return NULL; | |
422 return e; | |
423 } | |
424 | |
425 #define QUOTE(X) _QUOTE(X) | |
426 #define _QUOTE(X) #X | |
427 | |
428 static char _mysql___doc__[] = | |
429 "an adaptation of the MySQL C API (mostly)\n\ | |
430 \n\ | |
431 You probably are better off using MySQLdb instead of using this\n\ | |
432 module directly.\n\ | |
433 \n\ | |
434 In general, renaming goes from mysql_* to _mysql.*. _mysql.connect()\n\ | |
435 returns a connection object (MYSQL). Functions which expect MYSQL * as\n\ | |
436 an argument are now methods of the connection object. A number of things\n\ | |
437 return result objects (MYSQL_RES). Functions which expect MYSQL_RES * as\n\ | |
438 an argument are now methods of the result object. Deprecated functions\n\ | |
439 (as of 3.23) are NOT implemented.\n\ | |
440 "; | |
441 | |
442 PyMODINIT_FUNC | |
443 init_mysql(void) | |
444 { | |
445 PyObject *dict, *module, *emod, *edict, *version_tuple; | |
446 | |
447 module = Py_InitModule3("_mysql", _mysql_methods, _mysql___doc__); | |
448 if (!module) | |
449 return; /* this really should never happen */ | |
450 | |
451 /* Populate final object settings */ | |
452 _mysql_ConnectionObject_Type.ob_type = &PyType_Type; | |
453 _mysql_ResultObject_Type.ob_type = &PyType_Type; | |
454 _mysql_FieldObject_Type.ob_type = &PyType_Type; | |
455 _mysql_ConnectionObject_Type.tp_alloc = PyType_GenericAlloc; | |
456 _mysql_ConnectionObject_Type.tp_new = PyType_GenericNew; | |
457 _mysql_ConnectionObject_Type.tp_free = _PyObject_GC_Del; | |
458 _mysql_ResultObject_Type.tp_alloc = PyType_GenericAlloc; | |
459 _mysql_ResultObject_Type.tp_new = PyType_GenericNew; | |
460 _mysql_ResultObject_Type.tp_free = _PyObject_GC_Del; | |
461 _mysql_FieldObject_Type.tp_alloc = PyType_GenericAlloc; | |
462 _mysql_FieldObject_Type.tp_new = PyType_GenericNew; | |
463 _mysql_FieldObject_Type.tp_free = _PyObject_GC_Del; | |
464 | |
465 if (!(dict = PyModule_GetDict(module))) | |
466 goto error; | |
467 | |
468 /* Module constants */ | |
469 version_tuple = PyRun_String(QUOTE(version_info), Py_eval_input, | |
470 dict, dict); | |
471 if (PyModule_AddObject(module, "version_info", version_tuple) < 0) | |
472 goto error; | |
473 if (PyModule_AddStringConstant(module, "__version__", | |
474 QUOTE(__version__)) < 0) | |
475 goto error; | |
476 if (PyModule_AddStringConstant(module, "NULL", "NULL") < 0) | |
477 goto error; | |
478 | |
479 | |
480 /* Register types */ | |
481 if (PyDict_SetItemString(dict, "connection", | |
482 (PyObject *)&_mysql_ConnectionObject_Type)) | |
483 goto error; | |
484 Py_INCREF(&_mysql_ConnectionObject_Type); | |
485 if (PyDict_SetItemString(dict, "result", | |
486 (PyObject *)&_mysql_ResultObject_Type)) | |
487 goto error; | |
488 Py_INCREF(&_mysql_ResultObject_Type); | |
489 if (PyDict_SetItemString(dict, "field", | |
490 (PyObject *)&_mysql_FieldObject_Type)) | |
491 goto error; | |
492 Py_INCREF(&_mysql_FieldObject_Type); | |
493 | |
494 /* Reach into the exceptions module. */ | |
495 if (!(emod = PyImport_ImportModule("MySQLdb.exceptions"))) | |
496 goto error; | |
497 if (!(edict = PyModule_GetDict(emod))) goto error; | |
498 if (!(_mysql_MySQLError = | |
499 _mysql_NewException(dict, edict, "MySQLError"))) | |
500 goto error; | |
501 if (!(_mysql_Warning = | |
502 _mysql_NewException(dict, edict, "Warning"))) | |
503 goto error; | |
504 if (!(_mysql_Error = | |
505 _mysql_NewException(dict, edict, "Error"))) | |
506 goto error; | |
507 if (!(_mysql_InterfaceError = | |
508 _mysql_NewException(dict, edict, "InterfaceError"))) | |
509 goto error; | |
510 if (!(_mysql_DatabaseError = | |
511 _mysql_NewException(dict, edict, "DatabaseError"))) | |
512 goto error; | |
513 if (!(_mysql_DataError = | |
514 _mysql_NewException(dict, edict, "DataError"))) | |
515 goto error; | |
516 if (!(_mysql_OperationalError = | |
517 _mysql_NewException(dict, edict, "OperationalError"))) | |
518 goto error; | |
519 if (!(_mysql_IntegrityError = | |
520 _mysql_NewException(dict, edict, "IntegrityError"))) | |
521 goto error; | |
522 if (!(_mysql_InternalError = | |
523 _mysql_NewException(dict, edict, "InternalError"))) | |
524 goto error; | |
525 if (!(_mysql_ProgrammingError = | |
526 _mysql_NewException(dict, edict, "ProgrammingError"))) | |
527 goto error; | |
528 if (!(_mysql_NotSupportedError = | |
529 _mysql_NewException(dict, edict, "NotSupportedError"))) | |
530 goto error; | |
531 if (!(_mysql_error_map = PyDict_GetItemString(edict, "error_map"))) | |
532 goto error; | |
533 Py_DECREF(emod); | |
534 | |
535 error: | |
536 if (PyErr_Occurred()) | |
537 PyErr_SetString(PyExc_ImportError, | |
538 "_mysql: init failed"); | |
539 return; | |
540 } | |
541 | |
542 |