Skip to content

Commit 14b0524

Browse files
committed
This patch to the python bindings adds C versions of the often-used
query args quoting routines, as well as support for quoting lists e.g. dbc.execute("SELECT * FROM foo WHERE blah IN %s", ([1,2,3],)) Elliot Lee
1 parent 25b0b09 commit 14b0524

File tree

2 files changed

+174
-26
lines changed

2 files changed

+174
-26
lines changed

src/interfaces/python/pgdb.py

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -260,32 +260,38 @@ def setoutputsize(self, size, col = 0):
260260
pass
261261

262262

263-
def _quote(x):
264-
if type(x) == types.StringType:
265-
x = "'" + string.replace(
266-
string.replace(str(x), '\\', '\\\\'), "'", "''") + "'"
267-
268-
elif type(x) in (types.IntType, types.LongType, types.FloatType):
269-
pass
270-
elif x is None:
271-
x = 'NULL'
272-
elif hasattr(x, '__pg_repr__'):
273-
x = x.__pg_repr__()
274-
else:
275-
raise InterfaceError, 'do not know how to handle type %s' % type(x)
276-
277-
return x
278-
279-
def _quoteparams(s, params):
280-
if hasattr(params, 'has_key'):
281-
x = {}
282-
for k, v in params.items():
283-
x[k] = _quote(v)
284-
params = x
285-
else:
286-
params = tuple(map(_quote, params))
287-
288-
return s % params
263+
try:
264+
_quote = _pg.quote_fast
265+
_quoteparams = _pg.quoteparams_fast
266+
except NameError:
267+
def _quote(x):
268+
if type(x) == types.StringType:
269+
x = "'" + string.replace(
270+
string.replace(str(x), '\\', '\\\\'), "'", "''") + "'"
271+
272+
elif type(x) in (types.IntType, types.LongType, types.FloatType):
273+
pass
274+
elif x is None:
275+
x = 'NULL'
276+
elif type(x) in (types.ListType, types.TupleType):
277+
return '(%s)' % ','.join(map(lambda x: str(_quote(x)), x))
278+
elif hasattr(x, '__pg_repr__'):
279+
x = x.__pg_repr__()
280+
else:
281+
raise InterfaceError, 'do not know how to handle type %s' % type(x)
282+
283+
return x
284+
285+
def _quoteparams(s, params):
286+
if hasattr(params, 'has_key'):
287+
x = {}
288+
for k, v in params.items():
289+
x[k] = _quote(v)
290+
params = x
291+
else:
292+
params = tuple(map(_quote, params))
293+
294+
return s % params
289295

290296
### connection object
291297

src/interfaces/python/pgmodule.c

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3121,10 +3121,150 @@ pgsetdefport(PyObject * self, PyObject * args)
31213121
}
31223122
#endif /* DEFAULT_VARS */
31233123

3124+
static PyObject *comma_string = NULL;
3125+
3126+
static PyObject *
3127+
pgpy_quote_fast(PyObject *self, PyObject *args)
3128+
{
3129+
PyObject *x, *retval = NULL;
3130+
3131+
if(!PyArg_ParseTuple(args, "O:pgpy_quote_fast", &x))
3132+
return NULL;
3133+
3134+
if(x->ob_type == &PyInt_Type || x->ob_type == &PyLong_Type || x->ob_type == &PyFloat_Type)
3135+
{
3136+
Py_INCREF(retval = x);
3137+
}
3138+
else if(x == Py_None)
3139+
retval = PyString_FromString("NULL");
3140+
else if(x->ob_type == &PyString_Type)
3141+
{
3142+
char *in, *out, *ctmp;
3143+
int i, n, ct;
3144+
in = PyString_AS_STRING(x);
3145+
n = PyString_GET_SIZE(x);
3146+
3147+
for(i = ct = 0; i < n; i++)
3148+
if(in[i] == '\\' || in[i] == '\'')
3149+
ct++;
3150+
ctmp = out = alloca(n + ct + 10);
3151+
*(ctmp++) = '\'';
3152+
for(i = 0; i < n; i++)
3153+
{
3154+
if(in[i] == '\\')
3155+
*(ctmp++) = '\\';
3156+
if(in[i] == '\'')
3157+
*(ctmp++) = '\'';
3158+
*(ctmp++) = in[i];
3159+
}
3160+
*(ctmp++) = '\'';
3161+
*(ctmp++) = '\0';
3162+
retval = PyString_FromString(out);
3163+
}
3164+
else if(PySequence_Check(x))
3165+
{
3166+
int i, n = PySequence_Size(x);
3167+
PyObject *subout, *subargs, *subjoin = NULL;
3168+
3169+
subargs = PyTuple_New(1);
3170+
subout = PyTuple_New(n);
3171+
3172+
for(i = 0; i < n; i++)
3173+
{
3174+
PyObject *sub = PySequence_GetItem(x, i), *subres;
3175+
3176+
PyTuple_SetItem(subargs, 0, sub);
3177+
subres = pgpy_quote_fast(NULL, subargs);
3178+
if(!subres)
3179+
goto out;
3180+
3181+
if(!PyString_Check(subres))
3182+
{
3183+
PyObject *subres2 = PyObject_Str(subres);
3184+
3185+
if(!subres2)
3186+
goto out;
3187+
Py_DECREF(subres);
3188+
subres = subres2;
3189+
}
3190+
3191+
PyTuple_SetItem(subout, subres);
3192+
}
3193+
3194+
subjoin = _PyString_Join(comma_string, subout);
3195+
if(!subjoin)
3196+
goto out;
3197+
retval = PyString_FromFormat("(%s)", PyString_AS_STRING(subjoin));
3198+
3199+
out:
3200+
Py_INCREF(Py_None);
3201+
PyTuple_SetItem(subargs, 0, Py_None);
3202+
Py_DECREF(subargs);
3203+
Py_DECREF(subout);
3204+
Py_XDECREF(subjoin);
3205+
}
3206+
else
3207+
{
3208+
retval = PyEval_CallMethod(x, "__pg_repr__", "()");
3209+
if(!retval)
3210+
{
3211+
PyErr_Format(PyExc_TypeError, "Don't know how to quote type %s", ((PyTypeObject *)x->ob_type)->tp_name);
3212+
return NULL;
3213+
}
3214+
}
3215+
3216+
return retval;
3217+
}
3218+
3219+
static PyObject *
3220+
pgpy_quoteparams_fast(PyObject *self, PyObject *args)
3221+
{
3222+
PyObject *s, *params, *x = NULL, *retval;
3223+
3224+
if(!PyArg_ParseTuple("O!O:pgpy_quoteparams_fast", &PyString_Type, &s, &params))
3225+
return NULL;
3226+
3227+
if(PyDict_Check(params))
3228+
{
3229+
int i = 0;
3230+
PyObject *k, *v, *subargs;
3231+
3232+
x = PyDict_New();
3233+
subargs = PyTuple_New(1);
3234+
while(PyDict_Next(params, &i, &k, &v))
3235+
{
3236+
PyObject *qres;
3237+
3238+
PyTuple_SetItem(subargs, 0, v);
3239+
qres = pgpy_quote_fast(NULL, subargs);
3240+
if(!qres)
3241+
{
3242+
Py_DECREF(x);
3243+
Py_INCREF(Py_None);
3244+
PyTuple_SetItem(subargs, 0, Py_None);
3245+
Py_DECREF(subargs);
3246+
3247+
return NULL;
3248+
}
3249+
3250+
PyDict_SetItem(x, k, qres);
3251+
Py_DECREF(qres);
3252+
}
3253+
3254+
params = x;
3255+
}
3256+
3257+
retval = PyString_Format(s, params);
3258+
Py_XDECREF(x);
3259+
return retval;
3260+
}
3261+
31243262
/* List of functions defined in the module */
31253263

31263264
static struct PyMethodDef pg_methods[] = {
31273265
{"connect", (PyCFunction) pgconnect, 3, connect__doc__},
3266+
{"quote_fast", (PyCFunction) pgpy_quote_fast, METH_VARARGS},
3267+
{"quoteparams_fast", (PyCFunction) pgpy_quoteparams_fast, METH_VARARGS},
31283268

31293269
#ifdef DEFAULT_VARS
31303270
{"get_defhost", pggetdefhost, 1, getdefhost__doc__},
@@ -3178,6 +3318,8 @@ init_pg(void)
31783318
PyDict_SetItemString(dict, "RESULT_DDL", PyInt_FromLong(RESULT_DDL));
31793319
PyDict_SetItemString(dict, "RESULT_DQL", PyInt_FromLong(RESULT_DQL));
31803320

3321+
comma_string = PyString_InternFromString(",");
3322+
31813323
#ifdef LARGE_OBJECTS
31823324
/* create mode for large objects */
31833325
PyDict_SetItemString(dict, "INV_READ", PyInt_FromLong(INV_READ));

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy