Author: cito Date: Sat Jan 23 08:34:22 2016 New Revision: 780 Log: Refactoring of the decoding of columns
Add a helper function cast_value() and use that to cast
values to Python objects in both getresult() and dictresult().
Modified:
trunk/pgmodule.c
trunk/py3c.h
Modified: trunk/pgmodule.c
==============================================================================
--- trunk/pgmodule.c Fri Jan 22 11:49:58 2016 (r779)
+++ trunk/pgmodule.c Sat Jan 23 08:34:22 2016 (r780)
@@ -220,7 +220,7 @@
PyObject *
get_encoded_string(PyObject *unicode_obj, int encoding)
- {
+{
if (encoding == pg_encoding_utf8)
return PyUnicode_AsUTF8String(unicode_obj);
if (encoding == pg_encoding_latin1)
@@ -269,7 +269,7 @@
break;
case CASHOID:
- *a++ = PYGRES_MONEY;
+ *a++ = decimal_point ? PYGRES_MONEY :
PYGRES_DEFAULT;
break;
case BOOLOID:
@@ -278,7 +278,7 @@
case JSONOID:
case JSONBOID:
- *a++ = PYGRES_JSON;
+ *a++ = jsondecode ? PYGRES_JSON :
PYGRES_DEFAULT;
break;
default:
@@ -289,6 +289,109 @@
return array;
}
+/* cast string s with type, size and encoding to a Python object */
+PyObject *
+cast_value(char *s, int type, Py_ssize_t size, int encoding)
+{
+ PyObject *obj, *tmp_obj;
+ char cashbuf[64];
+ int k;
+
+ switch (type)
+ {
+ case PYGRES_JSON:
+ /* this type should only be passed when jsondecode is
set */
+ if (!jsondecode)
+ {
+ PyErr_SetString(PyExc_ValueError, "JSON decoder
is not set");
+ return NULL;
+ }
+
+ obj = get_decoded_string(s, size, encoding);
+ if (obj) /* was able to decode */
+ {
+ tmp_obj = Py_BuildValue("(O)", obj);
+ obj = PyObject_CallObject(jsondecode, tmp_obj);
+ Py_DECREF(tmp_obj);
+ }
+ break;
+
+ case PYGRES_INT:
+ obj = PyInt_FromString(s, NULL, 10);
+ break;
+
+ case PYGRES_LONG:
+ obj = PyLong_FromString(s, NULL, 10);
+ break;
+
+ case PYGRES_FLOAT:
+ tmp_obj = PyStr_FromString(s);
+ obj = PyFloat_FromString(tmp_obj);
+ Py_DECREF(tmp_obj);
+ break;
+
+ case PYGRES_MONEY:
+ /* type should only be passed when decimal_point is set
*/
+ if (!decimal_point)
+ {
+ PyErr_SetString(PyExc_ValueError, "Decimal
point is not set");
+ return NULL;
+ }
+
+ for (k = 0;
+ *s && k < sizeof(cashbuf)/sizeof(cashbuf[0]) -
1;
+ s++)
+ {
+ if (*s >= '0' && *s <= '9')
+ cashbuf[k++] = *s;
+ else if (*s == decimal_point)
+ cashbuf[k++] = '.';
+ else if (*s == '(' || *s == '-')
+ cashbuf[k++] = '-';
+ }
+ cashbuf[k] = '\0';
+ s = cashbuf;
+ /* FALLTHROUGH */ /* no break here */
+
+ case PYGRES_DECIMAL:
+ if (decimal)
+ {
+ tmp_obj = Py_BuildValue("(s)", s);
+ obj = PyEval_CallObject(decimal, tmp_obj);
+ }
+ else
+ {
+ tmp_obj = PyStr_FromString(s);
+ obj = PyFloat_FromString(tmp_obj);
+ }
+ Py_DECREF(tmp_obj);
+ break;
+
+ case PYGRES_BOOL:
+ /* convert to bool only if use_bool is set */
+ if (use_bool)
+ {
+ obj = *s == 't' ? Py_True : Py_False;
+ Py_INCREF(obj);
+ }
+ else
+ {
+ obj = PyStr_FromString(*s == 't' ? "t" : "f");
+ }
+ break;
+
+ default:
+#if IS_PY3
+ obj = get_decoded_string(s, size, encoding);
+ if (!obj) /* cannot decode */
+#endif
+ obj = PyBytes_FromStringAndSize(s, size);
+ }
+
+ return obj;
+}
+
+
/* internal wrapper for the notice receiver callback */
static void notice_receiver(void *arg, const PGresult *res)
{
@@ -3583,9 +3686,7 @@
m,
n,
*coltypes;
-#if IS_PY3
- int encoding;
-#endif
+ int encoding = self->encoding;
/* checks args (args == NULL for an internal call) */
if (args && !PyArg_ParseTuple(args, ""))
@@ -3601,10 +3702,6 @@
if (!(reslist = PyList_New(m)))
return NULL;
-#if IS_PY3
- encoding = self->encoding;
-#endif
-
coltypes = get_type_array(self->result, n);
for (i = 0; i < m; i++)
@@ -3628,112 +3725,18 @@
Py_INCREF(Py_None);
val = Py_None;
}
- else
+ else /* not null */
{
char *s = PQgetvalue(self->result, i, j);
- char cashbuf[64];
- int k;
- Py_ssize_t size;
- PyObject *tmp_obj;
+ Py_ssize_t size =
PQgetlength(self->result, i, j);;
- switch (coltypes[j])
+ if (PQfformat(self->result, j) == 0) /* text */
{
- case PYGRES_JSON:
- if (!jsondecode || /* no JSON
decoder available */
- PQfformat(self->result,
j) != 0) /* not text */
- goto default_case;
- size =
PQgetlength(self->result, i, j);
-#if IS_PY3
- val = get_decoded_string(s,
size, encoding);
-#else
- val = get_decoded_string(s,
size, self->encoding);
-#endif
- if (val) /* was able to decode
*/
- {
- tmp_obj =
Py_BuildValue("(O)", val);
- val =
PyObject_CallObject(jsondecode, tmp_obj);
- Py_DECREF(tmp_obj);
- }
- break;
-
- case PYGRES_INT:
- val = PyInt_FromString(s, NULL,
10);
- break;
-
- case PYGRES_LONG:
- val = PyLong_FromString(s,
NULL, 10);
- break;
-
- case PYGRES_FLOAT:
- tmp_obj = PyStr_FromString(s);
-#if IS_PY3
- val =
PyFloat_FromString(tmp_obj);
-#else
- val =
PyFloat_FromString(tmp_obj, NULL);
-#endif
- Py_DECREF(tmp_obj);
- break;
-
- case PYGRES_MONEY:
- /* convert to decimal only if
decimal point is set */
- if (!decimal_point) goto
default_case;
-
- for (k = 0;
- *s && k <
sizeof(cashbuf)/sizeof(cashbuf[0]) - 1;
- s++)
- {
- if (*s >= '0' && *s <=
'9')
- cashbuf[k++] =
*s;
- else if (*s ==
decimal_point)
- cashbuf[k++] =
'.';
- else if (*s == '(' ||
*s == '-')
- cashbuf[k++] =
'-';
- }
- cashbuf[k] = '\0';
- s = cashbuf;
- /* FALLTHROUGH */ /* no break
here */
-
- case PYGRES_DECIMAL:
- if (decimal)
- {
- tmp_obj =
Py_BuildValue("(s)", s);
- val =
PyEval_CallObject(decimal, tmp_obj);
- }
- else
- {
- tmp_obj =
PyStr_FromString(s);
-#if IS_PY3
- val =
PyFloat_FromString(tmp_obj);
-#else
- val =
PyFloat_FromString(tmp_obj, NULL);
-#endif
- }
- Py_DECREF(tmp_obj);
- break;
-
- case PYGRES_BOOL:
- /* convert to bool only if
bool_type is set */
- if (use_bool)
- {
- val = *s == 't' ?
Py_True : Py_False;
- Py_INCREF(val);
- break;
- }
- /* FALLTHROUGH */ /* no break
here */
-
- default:
- default_case:
- size =
PQgetlength(self->result, i, j);
-#if IS_PY3
- if (PQfformat(self->result, j)
== 0) /* text */
- {
- val =
get_decoded_string(s, size, encoding);
- if (!val) /* cannot
decode */
- val =
PyBytes_FromStringAndSize(s, size);
- }
- else
-#endif
- val =
PyBytes_FromStringAndSize(s, size);
+ val = cast_value(s, coltypes[j], size,
encoding);
+ }
+ else /* not text */
+ {
+ val = PyBytes_FromStringAndSize(s,
size);
}
}
@@ -3772,9 +3775,7 @@
m,
n,
*coltypes;
-#if IS_PY3
- int encoding;
-#endif
+ int encoding = self->encoding;
/* checks args (args == NULL for an internal call) */
if (args && !PyArg_ParseTuple(args, ""))
@@ -3790,10 +3791,6 @@
if (!(reslist = PyList_New(m)))
return NULL;
-#if IS_PY3
- encoding = self->encoding;
-#endif
-
coltypes = get_type_array(self->result, n);
for (i = 0; i < m; i++)
@@ -3817,112 +3814,18 @@
Py_INCREF(Py_None);
val = Py_None;
}
- else
+ else /* not null */
{
char *s = PQgetvalue(self->result, i, j);
- char cashbuf[64];
- int k;
- Py_ssize_t size;
- PyObject *tmp_obj;
+ Py_ssize_t size =
PQgetlength(self->result, i, j);;
- switch (coltypes[j])
+ if (PQfformat(self->result, j) == 0) /* text */
{
- case PYGRES_JSON:
- if (!jsondecode || /* no JSON
decoder available */
- PQfformat(self->result,
j) != 0) /* not text */
- goto default_case;
- size =
PQgetlength(self->result, i, j);
-#if IS_PY3
- val = get_decoded_string(s,
size, encoding);
-#else
- val = get_decoded_string(s,
size, self->encoding);
-#endif
- if (val) /* was able to decode
*/
- {
- tmp_obj =
Py_BuildValue("(O)", val);
- val =
PyObject_CallObject(jsondecode, tmp_obj);
- Py_DECREF(tmp_obj);
- }
- break;
-
- case PYGRES_INT:
- val = PyInt_FromString(s, NULL,
10);
- break;
-
- case PYGRES_LONG:
- val = PyLong_FromString(s,
NULL, 10);
- break;
-
- case PYGRES_FLOAT:
- tmp_obj = PyBytes_FromString(s);
-#if IS_PY3
- val =
PyFloat_FromString(tmp_obj);
-#else
- val =
PyFloat_FromString(tmp_obj, NULL);
-#endif
- Py_DECREF(tmp_obj);
- break;
-
- case PYGRES_MONEY:
- /* convert to decimal only if
decimal point is set */
- if (!decimal_point) goto
default_case;
-
- for (k = 0;
- *s && k <
sizeof(cashbuf)/sizeof(cashbuf[0]) - 1;
- s++)
- {
- if (*s >= '0' && *s <=
'9')
- cashbuf[k++] =
*s;
- else if (*s ==
decimal_point)
- cashbuf[k++] =
'.';
- else if (*s == '(' ||
*s == '-')
- cashbuf[k++] =
'-';
- }
- cashbuf[k] = '\0';
- s = cashbuf;
- /* FALLTHROUGH */ /* no break
here */
-
- case PYGRES_DECIMAL:
- if (decimal)
- {
- tmp_obj =
Py_BuildValue("(s)", s);
- val =
PyEval_CallObject(decimal, tmp_obj);
- }
- else
- {
- tmp_obj =
PyBytes_FromString(s);
-#if IS_PY3
- val =
PyFloat_FromString(tmp_obj);
-#else
- val =
PyFloat_FromString(tmp_obj, NULL);
-#endif
- }
- Py_DECREF(tmp_obj);
- break;
-
- case PYGRES_BOOL:
- /* convert to bool only if
bool_type is set */
- if (use_bool)
- {
- val = *s == 't' ?
Py_True : Py_False;
- Py_INCREF(val);
- break;
- }
- /* FALLTHROUGH */ /* no break
here */
-
- default:
- default_case:
- size =
PQgetlength(self->result, i, j);
-#if IS_PY3
- if (PQfformat(self->result, j)
== 0) /* text */
- {
- val =
get_decoded_string(s, size, encoding);
- if (!val) /* cannot
decode */
- val =
PyBytes_FromStringAndSize(s, size);
- }
- else
-#endif
- val =
PyBytes_FromStringAndSize(s, size);
+ val = cast_value(s, coltypes[j], size,
encoding);
+ }
+ else /* not text */
+ {
+ val = PyBytes_FromStringAndSize(s,
size);
}
}
Modified: trunk/py3c.h
==============================================================================
--- trunk/py3c.h Fri Jan 22 11:49:58 2016 (r779)
+++ trunk/py3c.h Sat Jan 23 08:34:22 2016 (r780)
@@ -105,6 +105,10 @@
#define PyBytes_ConcatAndDel PyString_ConcatAndDel
#define _PyBytes_Resize _PyString_Resize
+/* Floats */
+
+#define PyFloat_FromString(str) PyFloat_FromString(str, NULL)
+
/* Module init */
#define PyModuleDef_HEAD_INIT 0
_______________________________________________
PyGreSQL mailing list
[email protected]
https://mail.vex.net/mailman/listinfo.cgi/pygresql
