Changeset 780


Ignore:
Timestamp:
Jan 23, 2016, 8:34:22 AM (3 years ago)
Author:
cito
Message:

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().

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/pgmodule.c

    r774 r780  
    221221PyObject *
    222222get_encoded_string(PyObject *unicode_obj, int encoding)
    223  {
     223{
    224224        if (encoding == pg_encoding_utf8)
    225225                return PyUnicode_AsUTF8String(unicode_obj);
     
    270270
    271271                        case CASHOID:
    272                                 *a++ = PYGRES_MONEY;
     272                                *a++ = decimal_point ? PYGRES_MONEY : PYGRES_DEFAULT;
    273273                                break;
    274274
     
    279279                        case JSONOID:
    280280                        case JSONBOID:
    281                                 *a++ = PYGRES_JSON;
     281                                *a++ = jsondecode ? PYGRES_JSON : PYGRES_DEFAULT;
    282282                                break;
    283283
     
    289289        return array;
    290290}
     291
     292/* cast string s with type, size and encoding to a Python object */
     293PyObject *
     294cast_value(char *s, int type, Py_ssize_t size, int encoding)
     295{
     296        PyObject   *obj, *tmp_obj;
     297        char            cashbuf[64];
     298        int                     k;
     299
     300        switch (type)
     301        {
     302                case PYGRES_JSON:
     303                        /* this type should only be passed when jsondecode is set */
     304                        if (!jsondecode)
     305                        {
     306                                PyErr_SetString(PyExc_ValueError, "JSON decoder is not set");
     307                                return NULL;
     308                        }
     309
     310                        obj = get_decoded_string(s, size, encoding);
     311                        if (obj) /* was able to decode */
     312                        {
     313                                tmp_obj = Py_BuildValue("(O)", obj);
     314                                obj = PyObject_CallObject(jsondecode, tmp_obj);
     315                                Py_DECREF(tmp_obj);
     316                        }
     317                        break;
     318
     319                case PYGRES_INT:
     320                        obj = PyInt_FromString(s, NULL, 10);
     321                        break;
     322
     323                case PYGRES_LONG:
     324                        obj = PyLong_FromString(s, NULL, 10);
     325                        break;
     326
     327                case PYGRES_FLOAT:
     328                        tmp_obj = PyStr_FromString(s);
     329                        obj = PyFloat_FromString(tmp_obj);
     330                        Py_DECREF(tmp_obj);
     331                        break;
     332
     333                case PYGRES_MONEY:
     334                        /* type should only be passed when decimal_point is set */
     335                        if (!decimal_point)
     336                        {
     337                                PyErr_SetString(PyExc_ValueError, "Decimal point is not set");
     338                                return NULL;
     339                        }
     340
     341                        for (k = 0;
     342                                *s && k < sizeof(cashbuf)/sizeof(cashbuf[0]) - 1;
     343                                s++)
     344                        {
     345                                if (*s >= '0' && *s <= '9')
     346                                        cashbuf[k++] = *s;
     347                                else if (*s == decimal_point)
     348                                        cashbuf[k++] = '.';
     349                                else if (*s == '(' || *s == '-')
     350                                        cashbuf[k++] = '-';
     351                        }
     352                        cashbuf[k] = '\0';
     353                        s = cashbuf;
     354                        /* FALLTHROUGH */ /* no break here */
     355       
     356                case PYGRES_DECIMAL:
     357                        if (decimal)
     358                        {
     359                                tmp_obj = Py_BuildValue("(s)", s);
     360                                obj = PyEval_CallObject(decimal, tmp_obj);
     361                        }
     362                        else
     363                        {
     364                                tmp_obj = PyStr_FromString(s);
     365                                obj = PyFloat_FromString(tmp_obj);
     366                        }
     367                        Py_DECREF(tmp_obj);
     368                        break;
     369
     370                case PYGRES_BOOL:
     371                        /* convert to bool only if use_bool is set */
     372                        if (use_bool)
     373                        {
     374                                obj = *s == 't' ? Py_True : Py_False;
     375                                Py_INCREF(obj);
     376                        }
     377                        else
     378                        {
     379                                obj = PyStr_FromString(*s == 't' ? "t" : "f");
     380                        }
     381                        break;
     382
     383                default:
     384#if IS_PY3
     385                        obj = get_decoded_string(s, size, encoding);
     386                        if (!obj) /* cannot decode */
     387#endif
     388                        obj = PyBytes_FromStringAndSize(s, size);
     389        }
     390
     391        return obj;
     392}
     393
    291394
    292395/* internal wrapper for the notice receiver callback */
     
    35843687                                n,
    35853688                           *coltypes;
    3586 #if IS_PY3
    3587         int                     encoding;
    3588 #endif
     3689        int                     encoding = self->encoding;
    35893690
    35903691        /* checks args (args == NULL for an internal call) */
     
    36013702        if (!(reslist = PyList_New(m)))
    36023703                return NULL;
    3603 
    3604 #if IS_PY3
    3605         encoding = self->encoding;
    3606 #endif
    36073704
    36083705        coltypes = get_type_array(self->result, n);
     
    36293726                                val = Py_None;
    36303727                        }
    3631                         else
     3728                        else /* not null */
    36323729                        {
    36333730                                char       *s = PQgetvalue(self->result, i, j);
    3634                                 char            cashbuf[64];
    3635                                 int                     k;
    3636                                 Py_ssize_t      size;
    3637                                 PyObject   *tmp_obj;
    3638 
    3639                                 switch (coltypes[j])
     3731                                Py_ssize_t      size = PQgetlength(self->result, i, j);;
     3732
     3733                                if (PQfformat(self->result, j) == 0) /* text */
    36403734                                {
    3641                                         case PYGRES_JSON:
    3642                                                 if (!jsondecode || /* no JSON decoder available */
    3643                                                         PQfformat(self->result, j) != 0) /* not text */
    3644                                                         goto default_case;
    3645                                                 size = PQgetlength(self->result, i, j);
    3646 #if IS_PY3
    3647                                                 val = get_decoded_string(s, size, encoding);
    3648 #else
    3649                                                 val = get_decoded_string(s, size, self->encoding);
    3650 #endif
    3651                                                 if (val) /* was able to decode */
    3652                                                 {
    3653                                                         tmp_obj = Py_BuildValue("(O)", val);
    3654                                                         val = PyObject_CallObject(jsondecode, tmp_obj);
    3655                                                         Py_DECREF(tmp_obj);
    3656                                                 }
    3657                                                 break;
    3658 
    3659                                         case PYGRES_INT:
    3660                                                 val = PyInt_FromString(s, NULL, 10);
    3661                                                 break;
    3662 
    3663                                         case PYGRES_LONG:
    3664                                                 val = PyLong_FromString(s, NULL, 10);
    3665                                                 break;
    3666 
    3667                                         case PYGRES_FLOAT:
    3668                                                 tmp_obj = PyStr_FromString(s);
    3669 #if IS_PY3
    3670                                                 val = PyFloat_FromString(tmp_obj);
    3671 #else
    3672                                                 val = PyFloat_FromString(tmp_obj, NULL);
    3673 #endif
    3674                                                 Py_DECREF(tmp_obj);
    3675                                                 break;
    3676 
    3677                                         case PYGRES_MONEY:
    3678                                                 /* convert to decimal only if decimal point is set */
    3679                                                 if (!decimal_point) goto default_case;
    3680 
    3681                                                 for (k = 0;
    3682                                                         *s && k < sizeof(cashbuf)/sizeof(cashbuf[0]) - 1;
    3683                                                         s++)
    3684                                                 {
    3685                                                         if (*s >= '0' && *s <= '9')
    3686                                                                 cashbuf[k++] = *s;
    3687                                                         else if (*s == decimal_point)
    3688                                                                 cashbuf[k++] = '.';
    3689                                                         else if (*s == '(' || *s == '-')
    3690                                                                 cashbuf[k++] = '-';
    3691                                                 }
    3692                                                 cashbuf[k] = '\0';
    3693                                                 s = cashbuf;
    3694                                                 /* FALLTHROUGH */ /* no break here */
    3695 
    3696                                         case PYGRES_DECIMAL:
    3697                                                 if (decimal)
    3698                                                 {
    3699                                                         tmp_obj = Py_BuildValue("(s)", s);
    3700                                                         val = PyEval_CallObject(decimal, tmp_obj);
    3701                                                 }
    3702                                                 else
    3703                                                 {
    3704                                                         tmp_obj = PyStr_FromString(s);
    3705 #if IS_PY3
    3706                                                         val = PyFloat_FromString(tmp_obj);
    3707 #else
    3708                                                         val = PyFloat_FromString(tmp_obj, NULL);
    3709 #endif
    3710                                                 }
    3711                                                 Py_DECREF(tmp_obj);
    3712                                                 break;
    3713 
    3714                                         case PYGRES_BOOL:
    3715                                                 /* convert to bool only if bool_type is set */
    3716                                                 if (use_bool)
    3717                                                 {
    3718                                                         val = *s == 't' ? Py_True : Py_False;
    3719                                                         Py_INCREF(val);
    3720                                                         break;
    3721                                                 }
    3722                                                 /* FALLTHROUGH */ /* no break here */
    3723 
    3724                                         default:
    3725                                         default_case:
    3726                                                 size = PQgetlength(self->result, i, j);
    3727 #if IS_PY3
    3728                                                 if (PQfformat(self->result, j) == 0) /* text */
    3729                                                 {
    3730                                                         val = get_decoded_string(s, size, encoding);
    3731                                                         if (!val) /* cannot decode */
    3732                                                                 val = PyBytes_FromStringAndSize(s, size);
    3733                                                 }
    3734                                                 else
    3735 #endif
    3736                                                 val = PyBytes_FromStringAndSize(s, size);
     3735                                        val = cast_value(s, coltypes[j], size, encoding);
     3736                                }
     3737                                else /* not text */
     3738                                {
     3739                                        val = PyBytes_FromStringAndSize(s, size);
    37373740                                }
    37383741                        }
     
    37733776                                n,
    37743777                           *coltypes;
    3775 #if IS_PY3
    3776         int                     encoding;
    3777 #endif
     3778        int                     encoding = self->encoding;
    37783779
    37793780        /* checks args (args == NULL for an internal call) */
     
    37903791        if (!(reslist = PyList_New(m)))
    37913792                return NULL;
    3792 
    3793 #if IS_PY3
    3794         encoding = self->encoding;
    3795 #endif
    37963793
    37973794        coltypes = get_type_array(self->result, n);
     
    38183815                                val = Py_None;
    38193816                        }
    3820                         else
     3817                        else /* not null */
    38213818                        {
    38223819                                char       *s = PQgetvalue(self->result, i, j);
    3823                                 char            cashbuf[64];
    3824                                 int                     k;
    3825                                 Py_ssize_t      size;
    3826                                 PyObject   *tmp_obj;
    3827 
    3828                                 switch (coltypes[j])
     3820                                Py_ssize_t      size = PQgetlength(self->result, i, j);;
     3821
     3822                                if (PQfformat(self->result, j) == 0) /* text */
    38293823                                {
    3830                                         case PYGRES_JSON:
    3831                                                 if (!jsondecode || /* no JSON decoder available */
    3832                                                         PQfformat(self->result, j) != 0) /* not text */
    3833                                                         goto default_case;
    3834                                                 size = PQgetlength(self->result, i, j);
    3835 #if IS_PY3
    3836                                                 val = get_decoded_string(s, size, encoding);
    3837 #else
    3838                                                 val = get_decoded_string(s, size, self->encoding);
    3839 #endif
    3840                                                 if (val) /* was able to decode */
    3841                                                 {
    3842                                                         tmp_obj = Py_BuildValue("(O)", val);
    3843                                                         val = PyObject_CallObject(jsondecode, tmp_obj);
    3844                                                         Py_DECREF(tmp_obj);
    3845                                                 }
    3846                                                 break;
    3847 
    3848                                         case PYGRES_INT:
    3849                                                 val = PyInt_FromString(s, NULL, 10);
    3850                                                 break;
    3851 
    3852                                         case PYGRES_LONG:
    3853                                                 val = PyLong_FromString(s, NULL, 10);
    3854                                                 break;
    3855 
    3856                                         case PYGRES_FLOAT:
    3857                                                 tmp_obj = PyBytes_FromString(s);
    3858 #if IS_PY3
    3859                                                 val = PyFloat_FromString(tmp_obj);
    3860 #else
    3861                                                 val = PyFloat_FromString(tmp_obj, NULL);
    3862 #endif
    3863                                                 Py_DECREF(tmp_obj);
    3864                                                 break;
    3865 
    3866                                         case PYGRES_MONEY:
    3867                                                 /* convert to decimal only if decimal point is set */
    3868                                                 if (!decimal_point) goto default_case;
    3869 
    3870                                                 for (k = 0;
    3871                                                         *s && k < sizeof(cashbuf)/sizeof(cashbuf[0]) - 1;
    3872                                                         s++)
    3873                                                 {
    3874                                                         if (*s >= '0' && *s <= '9')
    3875                                                                 cashbuf[k++] = *s;
    3876                                                         else if (*s == decimal_point)
    3877                                                                 cashbuf[k++] = '.';
    3878                                                         else if (*s == '(' || *s == '-')
    3879                                                                 cashbuf[k++] = '-';
    3880                                                 }
    3881                                                 cashbuf[k] = '\0';
    3882                                                 s = cashbuf;
    3883                                                 /* FALLTHROUGH */ /* no break here */
    3884 
    3885                                         case PYGRES_DECIMAL:
    3886                                                 if (decimal)
    3887                                                 {
    3888                                                         tmp_obj = Py_BuildValue("(s)", s);
    3889                                                         val = PyEval_CallObject(decimal, tmp_obj);
    3890                                                 }
    3891                                                 else
    3892                                                 {
    3893                                                         tmp_obj = PyBytes_FromString(s);
    3894 #if IS_PY3
    3895                                                         val = PyFloat_FromString(tmp_obj);
    3896 #else
    3897                                                         val = PyFloat_FromString(tmp_obj, NULL);
    3898 #endif
    3899                                                 }
    3900                                                 Py_DECREF(tmp_obj);
    3901                                                 break;
    3902 
    3903                                         case PYGRES_BOOL:
    3904                                                 /* convert to bool only if bool_type is set */
    3905                                                 if (use_bool)
    3906                                                 {
    3907                                                         val = *s == 't' ? Py_True : Py_False;
    3908                                                         Py_INCREF(val);
    3909                                                         break;
    3910                                                 }
    3911                                                 /* FALLTHROUGH */ /* no break here */
    3912 
    3913                                         default:
    3914                                         default_case:
    3915                                                 size = PQgetlength(self->result, i, j);
    3916 #if IS_PY3
    3917                                                 if (PQfformat(self->result, j) == 0) /* text */
    3918                                                 {
    3919                                                         val = get_decoded_string(s, size, encoding);
    3920                                                         if (!val) /* cannot decode */
    3921                                                                 val = PyBytes_FromStringAndSize(s, size);
    3922                                                 }
    3923                                                 else
    3924 #endif
    3925                                                 val = PyBytes_FromStringAndSize(s, size);
     3824                                        val = cast_value(s, coltypes[j], size, encoding);
     3825                                }
     3826                                else /* not text */
     3827                                {
     3828                                        val = PyBytes_FromStringAndSize(s, size);
    39263829                                }
    39273830                        }
  • trunk/py3c.h

    r711 r780  
    106106#define _PyBytes_Resize _PyString_Resize
    107107
     108/* Floats */
     109
     110#define PyFloat_FromString(str) PyFloat_FromString(str, NULL)
     111
    108112/* Module init */
    109113
Note: See TracChangeset for help on using the changeset viewer.