Mercurial > p > mysql-python > mysqldb-2
comparison src/connections.c @ 67:98d968f5af11 MySQLdb
Reimplement MySQL->Python type conversion in C; much simpler and easier to deal with now. Hey, all my tests pass, so I guess that means I need to write some more tests.
author | adustman |
---|---|
date | Mon, 30 Mar 2009 20:21:24 +0000 |
parents | e606fd52e866 |
children | 18e5892a5aed |
comparison
equal
deleted
inserted
replaced
66:5a7c30cd9de2 | 67:98d968f5af11 |
---|---|
7 _mysql_ConnectionObject *self, | 7 _mysql_ConnectionObject *self, |
8 PyObject *args, | 8 PyObject *args, |
9 PyObject *kwargs) | 9 PyObject *kwargs) |
10 { | 10 { |
11 MYSQL *conn = NULL; | 11 MYSQL *conn = NULL; |
12 PyObject *conv = NULL; | 12 PyObject *decoder_stack = NULL; |
13 PyObject *ssl = NULL; | 13 PyObject *ssl = NULL; |
14 #if HAVE_OPENSSL | 14 #if HAVE_OPENSSL |
15 char *key = NULL, *cert = NULL, *ca = NULL, | 15 char *key = NULL, *cert = NULL, *ca = NULL, |
16 *capath = NULL, *cipher = NULL; | 16 *capath = NULL, *cipher = NULL; |
17 #endif | 17 #endif |
18 char *host = NULL, *user = NULL, *passwd = NULL, | 18 char *host = NULL, *user = NULL, *passwd = NULL, |
19 *db = NULL, *unix_socket = NULL; | 19 *db = NULL, *unix_socket = NULL; |
20 unsigned int port = 0; | 20 unsigned int port = 0; |
21 unsigned int client_flag = 0; | 21 unsigned int client_flag = 0; |
22 static char *kwlist[] = { "host", "user", "passwd", "db", "port", | 22 static char *kwlist[] = { "host", "user", "passwd", "db", "port", |
23 "unix_socket", "conv", | 23 "unix_socket", "decoder_stack", |
24 "connect_timeout", "compress", | 24 "connect_timeout", "compress", |
25 "named_pipe", "init_command", | 25 "named_pipe", "init_command", |
26 "read_default_file", "read_default_group", | 26 "read_default_file", "read_default_group", |
27 "client_flag", "ssl", | 27 "client_flag", "ssl", |
28 "local_infile", | 28 "local_infile", |
31 int compress = -1, named_pipe = -1, local_infile = -1; | 31 int compress = -1, named_pipe = -1, local_infile = -1; |
32 char *init_command=NULL, | 32 char *init_command=NULL, |
33 *read_default_file=NULL, | 33 *read_default_file=NULL, |
34 *read_default_group=NULL; | 34 *read_default_group=NULL; |
35 | 35 |
36 self->converter = NULL; | 36 self->decoder_stack = NULL; |
37 self->open = 0; | 37 self->open = 0; |
38 check_server_init(-1); | 38 check_server_init(-1); |
39 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ssssisOiiisssiOi:connect", | 39 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ssssisOiiisssiOi:connect", |
40 kwlist, | 40 kwlist, |
41 &host, &user, &passwd, &db, | 41 &host, &user, &passwd, &db, |
42 &port, &unix_socket, &conv, | 42 &port, &unix_socket, &decoder_stack, |
43 &connect_timeout, | 43 &connect_timeout, |
44 &compress, &named_pipe, | 44 &compress, &named_pipe, |
45 &init_command, &read_default_file, | 45 &init_command, &read_default_file, |
46 &read_default_group, | 46 &read_default_group, |
47 &client_flag, &ssl, | 47 &client_flag, &ssl, |
48 &local_infile | 48 &local_infile |
49 )) | 49 )) |
50 return -1; | 50 return -1; |
51 | 51 |
52 /* Keep the converter mapping or a blank mapping dict */ | 52 if (!decoder_stack) |
53 if (!conv) | 53 decoder_stack = PyList_New(0); |
54 conv = PyDict_New(); | |
55 else | 54 else |
56 Py_INCREF(conv); | 55 Py_INCREF(decoder_stack); |
57 if (!conv) | 56 self->decoder_stack = decoder_stack; |
58 return -1; | 57 |
59 self->converter = conv; | |
60 | |
61 #define _stringsuck(d,t,s) {t=PyMapping_GetItemString(s,#d);\ | 58 #define _stringsuck(d,t,s) {t=PyMapping_GetItemString(s,#d);\ |
62 if(t){d=PyString_AsString(t);Py_DECREF(t);}\ | 59 if(t){d=PyString_AsString(t);Py_DECREF(t);}\ |
63 PyErr_Clear();} | 60 PyErr_Clear();} |
64 | 61 |
65 if (ssl) { | 62 if (ssl) { |
146 integer, TCP/IP port to connect to\n\ | 143 integer, TCP/IP port to connect to\n\ |
147 \n\ | 144 \n\ |
148 unix_socket\n\ | 145 unix_socket\n\ |
149 string, location of unix_socket (UNIX-ish only)\n\ | 146 string, location of unix_socket (UNIX-ish only)\n\ |
150 \n\ | 147 \n\ |
151 conv\n\ | |
152 mapping, maps MySQL FIELD_TYPE.* to Python functions which\n\ | |
153 convert a string to the appropriate Python type\n\ | |
154 \n\ | |
155 connect_timeout\n\ | 148 connect_timeout\n\ |
156 number of seconds to wait before the connection\n\ | 149 number of seconds to wait before the connection\n\ |
157 attempt fails.\n\ | 150 attempt fails.\n\ |
158 \n\ | 151 \n\ |
159 compress\n\ | 152 compress\n\ |
199 static int _mysql_ConnectionObject_traverse( | 192 static int _mysql_ConnectionObject_traverse( |
200 _mysql_ConnectionObject *self, | 193 _mysql_ConnectionObject *self, |
201 visitproc visit, | 194 visitproc visit, |
202 void *arg) | 195 void *arg) |
203 { | 196 { |
204 if (self->converter) | 197 if (self->decoder_stack) |
205 return visit(self->converter, arg); | 198 return visit(self->decoder_stack, arg); |
206 return 0; | 199 return 0; |
207 } | 200 } |
208 | 201 |
209 static int _mysql_ConnectionObject_clear( | 202 static int _mysql_ConnectionObject_clear( |
210 _mysql_ConnectionObject *self) | 203 _mysql_ConnectionObject *self) |
211 { | 204 { |
212 Py_XDECREF(self->converter); | 205 Py_XDECREF(self->decoder_stack); |
213 self->converter = NULL; | 206 self->decoder_stack = NULL; |
214 return 0; | 207 return 0; |
215 } | 208 } |
216 | 209 |
217 extern PyObject * | 210 extern PyObject * |
218 _escape_item( | 211 _escape_item( |
219 PyObject *item, | 212 PyObject *item, |
220 PyObject *d); | 213 PyObject *d); |
221 | |
222 char _mysql_escape__doc__[] = | |
223 "escape(obj, dict) -- escape any special characters in object obj\n\ | |
224 using mapping dict to provide quoting functions for each type.\n\ | |
225 Returns a SQL literal string."; | |
226 PyObject * | |
227 _mysql_escape( | |
228 PyObject *self, | |
229 PyObject *args) | |
230 { | |
231 PyObject *o=NULL, *d=NULL; | |
232 if (!PyArg_ParseTuple(args, "O|O:escape", &o, &d)) | |
233 return NULL; | |
234 if (d) { | |
235 if (!PyMapping_Check(d)) { | |
236 PyErr_SetString(PyExc_TypeError, | |
237 "argument 2 must be a mapping"); | |
238 return NULL; | |
239 } | |
240 return _escape_item(o, d); | |
241 } else { | |
242 if (!self) { | |
243 PyErr_SetString(PyExc_TypeError, | |
244 "argument 2 must be a mapping"); | |
245 return NULL; | |
246 } | |
247 return _escape_item(o, | |
248 ((_mysql_ConnectionObject *) self)->converter); | |
249 } | |
250 } | |
251 | 214 |
252 char _mysql_escape_string__doc__[] = | 215 char _mysql_escape_string__doc__[] = |
253 "escape_string(s) -- quote any SQL-interpreted characters in string s.\n\ | 216 "escape_string(s) -- quote any SQL-interpreted characters in string s.\n\ |
254 \n\ | 217 If you want quotes around your value, use string_literal(s) instead.\n\ |
255 Use connection.escape_string(s), if you use it at all.\n\ | 218 "; |
256 _mysql.escape_string(s) cannot handle character sets. You are\n\ | |
257 probably better off using connection.escape(o) instead, since\n\ | |
258 it will escape entire sequences as well as strings."; | |
259 | 219 |
260 PyObject * | 220 PyObject * |
261 _mysql_escape_string( | 221 _mysql_escape_string( |
262 _mysql_ConnectionObject *self, | 222 _mysql_ConnectionObject *self, |
263 PyObject *args) | 223 PyObject *args) |
267 int len, size; | 227 int len, size; |
268 if (!PyArg_ParseTuple(args, "s#:escape_string", &in, &size)) return NULL; | 228 if (!PyArg_ParseTuple(args, "s#:escape_string", &in, &size)) return NULL; |
269 str = PyString_FromStringAndSize((char *) NULL, size*2+1); | 229 str = PyString_FromStringAndSize((char *) NULL, size*2+1); |
270 if (!str) return PyErr_NoMemory(); | 230 if (!str) return PyErr_NoMemory(); |
271 out = PyString_AS_STRING(str); | 231 out = PyString_AS_STRING(str); |
272 #if MYSQL_VERSION_ID < 32321 | 232 len = mysql_real_escape_string(&(self->connection), out, in, size); |
273 len = mysql_escape_string(out, in, size); | |
274 #else | |
275 check_server_init(NULL); | |
276 if (self && self->open) | |
277 len = mysql_real_escape_string(&(self->connection), out, in, size); | |
278 else | |
279 len = mysql_escape_string(out, in, size); | |
280 #endif | |
281 if (_PyString_Resize(&str, len) < 0) return NULL; | 233 if (_PyString_Resize(&str, len) < 0) return NULL; |
282 return (str); | 234 return (str); |
283 } | 235 } |
284 | 236 |
285 char _mysql_string_literal__doc__[] = | 237 char _mysql_string_literal__doc__[] = |
286 "string_literal(obj) -- converts object obj into a SQL string literal.\n\ | 238 "string_literal(s) -- converts string s into a SQL string literal.\n\ |
287 This means, any special SQL characters are escaped, and it is enclosed\n\ | 239 This means, any special SQL characters are escaped, and it is enclosed\n\ |
288 within single quotes. In other words, it performs:\n\ | 240 within single quotes. In other words, it performs:\n\ |
289 \n\ | 241 \n\ |
290 \"'%s'\" % escape_string(str(obj))\n\ | 242 \"'%s'\" % escape_string(s)\n\ |
291 \n\ | 243 "; |
292 Use connection.string_literal(obj), if you use it at all.\n\ | |
293 _mysql.string_literal(obj) cannot handle character sets."; | |
294 | 244 |
295 PyObject * | 245 PyObject * |
296 _mysql_string_literal( | 246 _mysql_string_literal( |
297 _mysql_ConnectionObject *self, | 247 _mysql_ConnectionObject *self, |
298 PyObject *args) | 248 PyObject *args) |
299 { | 249 { |
300 PyObject *str, *s, *o, *d; | 250 PyObject *str; |
301 char *in, *out; | 251 char *in, *out; |
302 int len, size; | 252 int len, size; |
303 if (!PyArg_ParseTuple(args, "O|O:string_literal", &o, &d)) return NULL; | 253 if (!PyArg_ParseTuple(args, "s#:string_literal", &in, &size)) return NULL; |
304 s = PyObject_Str(o); | |
305 if (!s) return NULL; | |
306 in = PyString_AsString(s); | |
307 size = PyString_GET_SIZE(s); | |
308 str = PyString_FromStringAndSize((char *) NULL, size*2+3); | 254 str = PyString_FromStringAndSize((char *) NULL, size*2+3); |
309 if (!str) return PyErr_NoMemory(); | 255 if (!str) return PyErr_NoMemory(); |
310 out = PyString_AS_STRING(str); | 256 out = PyString_AS_STRING(str); |
311 #if MYSQL_VERSION_ID < 32321 | 257 len = mysql_real_escape_string(&(self->connection), out+1, in, size); |
312 len = mysql_escape_string(out+1, in, size); | |
313 #else | |
314 check_server_init(NULL); | |
315 if (self && self->open) | |
316 len = mysql_real_escape_string(&(self->connection), out+1, in, size); | |
317 else | |
318 len = mysql_escape_string(out+1, in, size); | |
319 #endif | |
320 *out = *(out+len+1) = '\''; | 258 *out = *(out+len+1) = '\''; |
321 if (_PyString_Resize(&str, len+2) < 0) return NULL; | 259 if (_PyString_Resize(&str, len+2) < 0) return NULL; |
322 Py_DECREF(s); | |
323 return (str); | 260 return (str); |
324 } | 261 } |
325 | 262 |
326 static char _mysql_ConnectionObject_close__doc__[] = | 263 static char _mysql_ConnectionObject_close__doc__[] = |
327 "Close the connection. No further activity possible."; | 264 "Close the connection. No further activity possible."; |
992 { | 929 { |
993 PyObject *arglist=NULL, *kwarglist=NULL, *result=NULL; | 930 PyObject *arglist=NULL, *kwarglist=NULL, *result=NULL; |
994 _mysql_ResultObject *r=NULL; | 931 _mysql_ResultObject *r=NULL; |
995 | 932 |
996 check_connection(self); | 933 check_connection(self); |
997 arglist = Py_BuildValue("(OiO)", self, 0, self->converter); | 934 arglist = Py_BuildValue("(OiO)", self, 0, self->decoder_stack); |
998 if (!arglist) goto error; | 935 if (!arglist) goto error; |
999 kwarglist = PyDict_New(); | 936 kwarglist = PyDict_New(); |
1000 if (!kwarglist) goto error; | 937 if (!kwarglist) goto error; |
1001 r = MyAlloc(_mysql_ResultObject, _mysql_ResultObject_Type); | 938 r = MyAlloc(_mysql_ResultObject, _mysql_ResultObject_Type); |
1002 if (!r) goto error; | 939 if (!r) goto error; |
1052 { | 989 { |
1053 PyObject *arglist=NULL, *kwarglist=NULL, *result=NULL; | 990 PyObject *arglist=NULL, *kwarglist=NULL, *result=NULL; |
1054 _mysql_ResultObject *r=NULL; | 991 _mysql_ResultObject *r=NULL; |
1055 | 992 |
1056 check_connection(self); | 993 check_connection(self); |
1057 arglist = Py_BuildValue("(OiO)", self, 1, self->converter); | 994 arglist = Py_BuildValue("(OiO)", self, 1, self->decoder_stack); |
1058 if (!arglist) return NULL; | 995 if (!arglist) return NULL; |
1059 kwarglist = PyDict_New(); | 996 kwarglist = PyDict_New(); |
1060 if (!kwarglist) goto error; | 997 if (!kwarglist) goto error; |
1061 r = MyAlloc(_mysql_ResultObject, _mysql_ResultObject_Type); | 998 r = MyAlloc(_mysql_ResultObject, _mysql_ResultObject_Type); |
1062 if (!r) goto error; | 999 if (!r) goto error; |
1195 (PyCFunction)_mysql_ConnectionObject_dump_debug_info, | 1132 (PyCFunction)_mysql_ConnectionObject_dump_debug_info, |
1196 METH_NOARGS, | 1133 METH_NOARGS, |
1197 _mysql_ConnectionObject_dump_debug_info__doc__ | 1134 _mysql_ConnectionObject_dump_debug_info__doc__ |
1198 }, | 1135 }, |
1199 { | 1136 { |
1200 "escape", | |
1201 (PyCFunction)_mysql_escape, | |
1202 METH_VARARGS, | |
1203 _mysql_escape__doc__ | |
1204 }, | |
1205 { | |
1206 "escape_string", | 1137 "escape_string", |
1207 (PyCFunction)_mysql_escape_string, | 1138 (PyCFunction)_mysql_escape_string, |
1208 METH_VARARGS, | 1139 METH_VARARGS, |
1209 _mysql_escape_string__doc__ | 1140 _mysql_escape_string__doc__ |
1210 }, | 1141 }, |
1325 offsetof(_mysql_ConnectionObject, open), | 1256 offsetof(_mysql_ConnectionObject, open), |
1326 RO, | 1257 RO, |
1327 "True if connection is open" | 1258 "True if connection is open" |
1328 }, | 1259 }, |
1329 { | 1260 { |
1330 "converter", | 1261 "decoder_stack", |
1331 T_OBJECT, | 1262 T_OBJECT, |
1332 offsetof(_mysql_ConnectionObject, converter), | 1263 offsetof(_mysql_ConnectionObject, decoder_stack), |
1333 0, | 1264 0, |
1334 "Type conversion mapping" | 1265 "Type decoder stack" |
1335 }, | 1266 }, |
1336 { | 1267 { |
1337 "server_capabilities", | 1268 "server_capabilities", |
1338 T_UINT, | 1269 T_UINT, |
1339 offsetof(_mysql_ConnectionObject, connection.server_capabilities), | 1270 offsetof(_mysql_ConnectionObject, connection.server_capabilities), |