Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)