source: trunk/pginternal.c

Last change on this file was 1002, checked in by cito, 5 months ago

Use same prefix for all C files

So that they are not scattered among the other files
in the root directory.

File size: 42.6 KB
Line 
1/*
2 * $Id: pginternal.c 985 2019-04-22 22:07:43Z cito $
3 *
4 * PyGreSQL - a Python interface for the PostgreSQL database.
5 *
6 * Internal functions - this file is part a of the C extension module.
7 *
8 * Copyright (c) 2019 by the PyGreSQL Development Team
9 *
10 * Please see the LICENSE.TXT file for specific restrictions.
11 *
12 */
13
14/* PyGreSQL internal types */
15
16/* Simple types */
17#define PYGRES_INT 1
18#define PYGRES_LONG 2
19#define PYGRES_FLOAT 3
20#define PYGRES_DECIMAL 4
21#define PYGRES_MONEY 5
22#define PYGRES_BOOL 6
23/* Text based types */
24#define PYGRES_TEXT 8
25#define PYGRES_BYTEA 9
26#define PYGRES_JSON 10
27#define PYGRES_OTHER 11
28/* Array types */
29#define PYGRES_ARRAY 16
30
31/* Shared functions for encoding and decoding strings */
32
33static PyObject *
34get_decoded_string(const char *str, Py_ssize_t size, int encoding)
35{
36    if (encoding == pg_encoding_utf8)
37        return PyUnicode_DecodeUTF8(str, size, "strict");
38    if (encoding == pg_encoding_latin1)
39        return PyUnicode_DecodeLatin1(str, size, "strict");
40    if (encoding == pg_encoding_ascii)
41        return PyUnicode_DecodeASCII(str, size, "strict");
42    /* encoding name should be properly translated to Python here */
43    return PyUnicode_Decode(str, size,
44        pg_encoding_to_char(encoding), "strict");
45}
46
47static PyObject *
48get_encoded_string(PyObject *unicode_obj, int encoding)
49{
50    if (encoding == pg_encoding_utf8)
51        return PyUnicode_AsUTF8String(unicode_obj);
52    if (encoding == pg_encoding_latin1)
53        return PyUnicode_AsLatin1String(unicode_obj);
54    if (encoding == pg_encoding_ascii)
55        return PyUnicode_AsASCIIString(unicode_obj);
56    /* encoding name should be properly translated to Python here */
57    return PyUnicode_AsEncodedString(unicode_obj,
58        pg_encoding_to_char(encoding), "strict");
59}
60
61/* Helper functions */
62
63/* Get PyGreSQL internal types for a PostgreSQL type. */
64static int
65get_type(Oid pgtype)
66{
67    int t;
68
69    switch (pgtype) {
70        /* simple types */
71
72        case INT2OID:
73        case INT4OID:
74        case CIDOID:
75        case OIDOID:
76        case XIDOID:
77            t = PYGRES_INT;
78            break;
79
80        case INT8OID:
81            t = PYGRES_LONG;
82            break;
83
84        case FLOAT4OID:
85        case FLOAT8OID:
86            t = PYGRES_FLOAT;
87            break;
88
89        case NUMERICOID:
90            t = PYGRES_DECIMAL;
91            break;
92
93        case CASHOID:
94            t = decimal_point ? PYGRES_MONEY : PYGRES_TEXT;
95            break;
96
97        case BOOLOID:
98            t = PYGRES_BOOL;
99            break;
100
101        case BYTEAOID:
102            t = bytea_escaped ? PYGRES_TEXT : PYGRES_BYTEA;
103            break;
104
105        case JSONOID:
106        case JSONBOID:
107            t = jsondecode ? PYGRES_JSON : PYGRES_TEXT;
108            break;
109
110        case BPCHAROID:
111        case CHAROID:
112        case TEXTOID:
113        case VARCHAROID:
114        case NAMEOID:
115        case REGTYPEOID:
116            t = PYGRES_TEXT;
117            break;
118
119        /* array types */
120
121        case INT2ARRAYOID:
122        case INT4ARRAYOID:
123        case CIDARRAYOID:
124        case OIDARRAYOID:
125        case XIDARRAYOID:
126            t = array_as_text ? PYGRES_TEXT : (PYGRES_INT | PYGRES_ARRAY);
127            break;
128
129        case INT8ARRAYOID:
130            t = array_as_text ? PYGRES_TEXT : (PYGRES_LONG | PYGRES_ARRAY);
131            break;
132
133        case FLOAT4ARRAYOID:
134        case FLOAT8ARRAYOID:
135            t = array_as_text ? PYGRES_TEXT : (PYGRES_FLOAT | PYGRES_ARRAY);
136            break;
137
138        case NUMERICARRAYOID:
139            t = array_as_text ? PYGRES_TEXT : (PYGRES_DECIMAL | PYGRES_ARRAY);
140            break;
141
142        case MONEYARRAYOID:
143            t = array_as_text ? PYGRES_TEXT : ((decimal_point ?
144                PYGRES_MONEY : PYGRES_TEXT) | PYGRES_ARRAY);
145            break;
146
147        case BOOLARRAYOID:
148            t = array_as_text ? PYGRES_TEXT : (PYGRES_BOOL | PYGRES_ARRAY);
149            break;
150
151        case BYTEAARRAYOID:
152            t = array_as_text ? PYGRES_TEXT : ((bytea_escaped ?
153                PYGRES_TEXT : PYGRES_BYTEA) | PYGRES_ARRAY);
154            break;
155
156        case JSONARRAYOID:
157        case JSONBARRAYOID:
158            t = array_as_text ? PYGRES_TEXT : ((jsondecode ?
159                PYGRES_JSON : PYGRES_TEXT) | PYGRES_ARRAY);
160            break;
161
162        case BPCHARARRAYOID:
163        case CHARARRAYOID:
164        case TEXTARRAYOID:
165        case VARCHARARRAYOID:
166        case NAMEARRAYOID:
167        case REGTYPEARRAYOID:
168            t = array_as_text ? PYGRES_TEXT : (PYGRES_TEXT | PYGRES_ARRAY);
169            break;
170
171        default:
172            t = PYGRES_OTHER;
173    }
174
175    return t;
176}
177
178/* Get PyGreSQL column types for all result columns. */
179static int *
180get_col_types(PGresult *result, int nfields)
181{
182    int *types, *t, j;
183
184    if (!(types = PyMem_Malloc(sizeof(int) * nfields))) {
185        return (int*) PyErr_NoMemory();
186    }
187
188    for (j = 0, t = types; j < nfields; ++j) {
189        *t++ = get_type(PQftype(result, j));
190    }
191
192    return types;
193}
194
195/* Cast a bytea encoded text based type to a Python object.
196   This assumes the text is null-terminated character string. */
197static PyObject *
198cast_bytea_text(char *s)
199{
200    PyObject *obj;
201    char *tmp_str;
202    size_t str_len;
203
204    /* this function should not be called when bytea_escaped is set */
205    tmp_str = (char *) PQunescapeBytea((unsigned char*) s, &str_len);
206    obj = PyBytes_FromStringAndSize(tmp_str, str_len);
207    if (tmp_str) {
208        PQfreemem(tmp_str);
209    }
210    return obj;
211}
212
213/* Cast a text based type to a Python object.
214   This needs the character string, size and encoding. */
215static PyObject *
216cast_sized_text(char *s, Py_ssize_t size, int encoding, int type)
217{
218    PyObject *obj, *tmp_obj;
219    char *tmp_str;
220    size_t str_len;
221
222    switch (type) { /* this must be the PyGreSQL internal type */
223
224        case PYGRES_BYTEA:
225            /* this type should not be passed when bytea_escaped is set */
226            /* we need to add a null byte */
227            tmp_str = (char *) PyMem_Malloc(size + 1);
228            if (!tmp_str) {
229                return PyErr_NoMemory();
230            }
231            memcpy(tmp_str, s, size);
232            s = tmp_str; *(s + size) = '\0';
233            tmp_str = (char *) PQunescapeBytea((unsigned char*) s, &str_len);
234            PyMem_Free(s);
235            if (!tmp_str) return PyErr_NoMemory();
236            obj = PyBytes_FromStringAndSize(tmp_str, str_len);
237            if (tmp_str) {
238                PQfreemem(tmp_str);
239            }
240            break;
241
242        case PYGRES_JSON:
243            /* this type should only be passed when jsondecode is set */
244            obj = get_decoded_string(s, size, encoding);
245            if (obj && jsondecode) { /* was able to decode */
246                tmp_obj = Py_BuildValue("(O)", obj);
247                obj = PyObject_CallObject(jsondecode, tmp_obj);
248                Py_DECREF(tmp_obj);
249            }
250            break;
251
252        default:  /* PYGRES_TEXT */
253#if IS_PY3
254            obj = get_decoded_string(s, size, encoding);
255            if (!obj) /* cannot decode */
256#endif
257            obj = PyBytes_FromStringAndSize(s, size);
258    }
259
260    return obj;
261}
262
263/* Cast an arbitrary type to a Python object using a callback function.
264   This needs the character string, size, encoding, the Postgres type
265   and the external typecast function to be called. */
266static PyObject *
267cast_other(char *s, Py_ssize_t size, int encoding, Oid pgtype,
268           PyObject *cast_hook)
269{
270    PyObject *obj;
271
272    obj = cast_sized_text(s, size, encoding, PYGRES_TEXT);
273
274    if (cast_hook) {
275        PyObject *tmp_obj = obj;
276        obj = PyObject_CallFunction(cast_hook, "(OI)", obj, pgtype);
277        Py_DECREF(tmp_obj);
278    }
279    return obj;
280}
281
282/* Cast a simple type to a Python object.
283   This needs a character string representation with a given size. */
284static PyObject *
285cast_sized_simple(char *s, Py_ssize_t size, int type)
286{
287    PyObject *obj, *tmp_obj;
288    char buf[64], *t;
289    int i, j, n;
290
291    switch (type) { /* this must be the PyGreSQL internal type */
292
293        case PYGRES_INT:
294            n = sizeof(buf) / sizeof(buf[0]) - 1;
295            if ((int) size < n) {
296                n = (int) size;
297            }
298            for (i = 0, t = buf; i < n; ++i) {
299                *t++ = *s++;
300            }
301            *t = '\0';
302            obj = PyInt_FromString(buf, NULL, 10);
303            break;
304
305        case PYGRES_LONG:
306            n = sizeof(buf) / sizeof(buf[0]) - 1;
307            if ((int) size < n) {
308                n = (int) size;
309            }
310            for (i = 0, t = buf; i < n; ++i) {
311                *t++ = *s++;
312            }
313            *t = '\0';
314            obj = PyLong_FromString(buf, NULL, 10);
315            break;
316
317        case PYGRES_FLOAT:
318            tmp_obj = PyStr_FromStringAndSize(s, size);
319            obj = PyFloat_FromString(tmp_obj);
320            Py_DECREF(tmp_obj);
321            break;
322
323        case PYGRES_MONEY:
324            /* this type should only be passed when decimal_point is set */
325            n = sizeof(buf) / sizeof(buf[0]) - 1;
326            for (i = 0, j = 0; i < size && j < n; ++i, ++s) {
327                if (*s >= '0' && *s <= '9') {
328                    buf[j++] = *s;
329                }
330                else if (*s == decimal_point) {
331                    buf[j++] = '.';
332                }
333                else if (*s == '(' || *s == '-') {
334                    buf[j++] = '-';
335                }
336            }
337            if (decimal) {
338                buf[j] = '\0';
339                obj = PyObject_CallFunction(decimal, "(s)", buf);
340            }
341            else {
342                tmp_obj = PyStr_FromString(buf);
343                obj = PyFloat_FromString(tmp_obj);
344                Py_DECREF(tmp_obj);
345
346            }
347            break;
348
349        case PYGRES_DECIMAL:
350            tmp_obj = PyStr_FromStringAndSize(s, size);
351            obj = decimal ? PyObject_CallFunctionObjArgs(
352                decimal, tmp_obj, NULL) : PyFloat_FromString(tmp_obj);
353            Py_DECREF(tmp_obj);
354            break;
355
356        case PYGRES_BOOL:
357            /* convert to bool only if bool_as_text is not set */
358            if (bool_as_text) {
359                obj = PyStr_FromString(*s == 't' ? "t" : "f");
360            }
361            else {
362                obj = *s == 't' ? Py_True : Py_False;
363                Py_INCREF(obj);
364            }
365            break;
366
367        default:
368            /* other types should never be passed, use cast_sized_text */
369            obj = PyStr_FromStringAndSize(s, size);
370    }
371
372    return obj;
373}
374
375/* Cast a simple type to a Python object.
376   This needs a null-terminated character string representation. */
377static PyObject *
378cast_unsized_simple(char *s, int type)
379{
380    PyObject *obj, *tmp_obj;
381    char buf[64];
382    int j, n;
383
384    switch (type) { /* this must be the PyGreSQL internal type */
385
386        case PYGRES_INT:
387            obj = PyInt_FromString(s, NULL, 10);
388            break;
389
390        case PYGRES_LONG:
391            obj = PyLong_FromString(s, NULL, 10);
392            break;
393
394        case PYGRES_FLOAT:
395            tmp_obj = PyStr_FromString(s);
396            obj = PyFloat_FromString(tmp_obj);
397            Py_DECREF(tmp_obj);
398            break;
399
400        case PYGRES_MONEY:
401            /* this type should only be passed when decimal_point is set */
402            n = sizeof(buf) / sizeof(buf[0]) - 1;
403            for (j = 0; *s && j < n; ++s) {
404                if (*s >= '0' && *s <= '9') {
405                    buf[j++] = *s;
406                }
407                else if (*s == decimal_point) {
408                    buf[j++] = '.';
409                }
410                else if (*s == '(' || *s == '-') {
411                    buf[j++] = '-';
412                }
413            }
414            buf[j] = '\0'; s = buf;
415            /* FALLTHROUGH */ /* no break here */
416
417        case PYGRES_DECIMAL:
418            if (decimal) {
419                obj = PyObject_CallFunction(decimal, "(s)", s);
420            }
421            else {
422                tmp_obj = PyStr_FromString(s);
423                obj = PyFloat_FromString(tmp_obj);
424                Py_DECREF(tmp_obj);
425            }
426            break;
427
428        case PYGRES_BOOL:
429            /* convert to bool only if bool_as_text is not set */
430            if (bool_as_text) {
431                obj = PyStr_FromString(*s == 't' ? "t" : "f");
432            }
433            else {
434                obj = *s == 't' ? Py_True : Py_False;
435                Py_INCREF(obj);
436            }
437            break;
438
439        default:
440            /* other types should never be passed, use cast_sized_text */
441            obj = PyStr_FromString(s);
442    }
443
444    return obj;
445}
446
447/* Quick case insensitive check if given sized string is null. */
448#define STR_IS_NULL(s, n) (n == 4 && \
449    (s[0] == 'n' || s[0] == 'N') && \
450    (s[1] == 'u' || s[1] == 'U') && \
451    (s[2] == 'l' || s[2] == 'L') && \
452    (s[3] == 'l' || s[3] == 'L'))
453
454/* Cast string s with size and encoding to a Python list,
455   using the input and output syntax for arrays.
456   Use internal type or cast function to cast elements.
457   The parameter delim specifies the delimiter for the elements,
458   since some types do not use the default delimiter of a comma. */
459static PyObject *
460cast_array(char *s, Py_ssize_t size, int encoding,
461     int type, PyObject *cast, char delim)
462{
463    PyObject *result, *stack[MAX_ARRAY_DEPTH];
464    char *end = s + size, *t;
465    int depth, ranges = 0, level = 0;
466
467    if (type) {
468        type &= ~PYGRES_ARRAY; /* get the base type */
469        if (!type) type = PYGRES_TEXT;
470    }
471    if (!delim) {
472        delim = ',';
473    }
474    else if (delim == '{' || delim =='}' || delim=='\\') {
475        PyErr_SetString(PyExc_ValueError, "Invalid array delimiter");
476        return NULL;
477    }
478
479    /* strip blanks at the beginning */
480    while (s != end && *s == ' ') ++s;
481    if (*s == '[') { /* dimension ranges */
482        int valid;
483
484        for (valid = 0; !valid;) {
485            if (s == end || *s++ != '[') break;
486            while (s != end && *s == ' ') ++s;
487            if (s != end && (*s == '+' || *s == '-')) ++s;
488            if (s == end || *s < '0' || *s > '9') break;
489            while (s != end && *s >= '0' && *s <= '9') ++s;
490            if (s == end || *s++ != ':') break;
491            if (s != end && (*s == '+' || *s == '-')) ++s;
492            if (s == end || *s < '0' || *s > '9') break;
493            while (s != end && *s >= '0' && *s <= '9') ++s;
494            if (s == end || *s++ != ']') break;
495            while (s != end && *s == ' ') ++s;
496            ++ranges;
497            if (s != end && *s == '=') {
498                do ++s; while (s != end && *s == ' ');
499                valid = 1;
500            }
501        }
502        if (!valid) {
503            PyErr_SetString(PyExc_ValueError, "Invalid array dimensions");
504            return NULL;
505        }
506    }
507    for (t = s, depth = 0; t != end && (*t == '{' || *t == ' '); ++t) {
508        if (*t == '{') ++depth;
509    }
510    if (!depth) {
511        PyErr_SetString(PyExc_ValueError,
512                        "Array must start with a left brace");
513        return NULL;
514    }
515    if (ranges && depth != ranges) {
516        PyErr_SetString(PyExc_ValueError,
517                        "Array dimensions do not match content");
518        return NULL;
519    }
520    if (depth > MAX_ARRAY_DEPTH) {
521        PyErr_SetString(PyExc_ValueError, "Array is too deeply nested");
522        return NULL;
523    }
524    depth--; /* next level of parsing */
525    result = PyList_New(0);
526    if (!result) return NULL;
527    do ++s; while (s != end && *s == ' ');
528    /* everything is set up, start parsing the array */
529    while (s != end) {
530        if (*s == '}') {
531            PyObject *subresult;
532
533            if (!level) break; /* top level array ended */
534            do ++s; while (s != end && *s == ' ');
535            if (s == end) break; /* error */
536            if (*s == delim) {
537                do ++s; while (s != end && *s == ' ');
538                if (s == end) break; /* error */
539                if (*s != '{') {
540                    PyErr_SetString(PyExc_ValueError,
541                                    "Subarray expected but not found");
542                    Py_DECREF(result); return NULL;
543                }
544            }
545            else if (*s != '}') break; /* error */
546            subresult = result;
547            result = stack[--level];
548            if (PyList_Append(result, subresult)) {
549                Py_DECREF(result); return NULL;
550            }
551        }
552        else if (level == depth) { /* we expect elements at this level */
553            PyObject *element;
554            char *estr;
555            Py_ssize_t esize;
556            int escaped = 0;
557
558            if (*s == '{') {
559                PyErr_SetString(PyExc_ValueError,
560                                "Subarray found where not expected");
561                Py_DECREF(result); return NULL;
562            }
563            if (*s == '"') { /* quoted element */
564                estr = ++s;
565                while (s != end && *s != '"') {
566                    if (*s == '\\') {
567                        ++s; if (s == end) break;
568                        escaped = 1;
569                    }
570                    ++s;
571                }
572                esize = s - estr;
573                do ++s; while (s != end && *s == ' ');
574            }
575            else { /* unquoted element */
576                estr = s;
577                /* can contain blanks inside */
578                while (s != end && *s != '"' &&
579                       *s != '{' && *s != '}' && *s != delim)
580                {
581                    if (*s == '\\') {
582                        ++s; if (s == end) break;
583                        escaped = 1;
584                    }
585                    ++s;
586                }
587                t = s; while (t > estr && *(t - 1) == ' ') --t;
588                if (!(esize = t - estr)) {
589                    s = end; break; /* error */
590                }
591                if (STR_IS_NULL(estr, esize)) /* NULL gives None */
592                    estr = NULL;
593            }
594            if (s == end) break; /* error */
595            if (estr) {
596                if (escaped) {
597                    char *r;
598                    Py_ssize_t i;
599
600                    /* create unescaped string */
601                    t = estr;
602                    estr = (char *) PyMem_Malloc(esize);
603                    if (!estr) {
604                        Py_DECREF(result); return PyErr_NoMemory();
605                    }
606                    for (i = 0, r = estr; i < esize; ++i) {
607                        if (*t == '\\') ++t, ++i;
608                        *r++ = *t++;
609                    }
610                    esize = r - estr;
611                }
612                if (type) { /* internal casting of base type */
613                    if (type & PYGRES_TEXT)
614                        element = cast_sized_text(estr, esize, encoding, type);
615                    else
616                        element = cast_sized_simple(estr, esize, type);
617                }
618                else { /* external casting of base type */
619#if IS_PY3
620                    element = encoding == pg_encoding_ascii ? NULL :
621                        get_decoded_string(estr, esize, encoding);
622                    if (!element) /* no decoding necessary or possible */
623#endif
624                    element = PyBytes_FromStringAndSize(estr, esize);
625                    if (element && cast) {
626                        PyObject *tmp = element;
627                        element = PyObject_CallFunctionObjArgs(
628                            cast, element, NULL);
629                        Py_DECREF(tmp);
630                    }
631                }
632                if (escaped) PyMem_Free(estr);
633                if (!element) {
634                    Py_DECREF(result); return NULL;
635                }
636            }
637            else {
638                Py_INCREF(Py_None); element = Py_None;
639            }
640            if (PyList_Append(result, element)) {
641                Py_DECREF(element); Py_DECREF(result); return NULL;
642            }
643            Py_DECREF(element);
644            if (*s == delim) {
645                do ++s; while (s != end && *s == ' ');
646                if (s == end) break; /* error */
647            }
648            else if (*s != '}') break; /* error */
649        }
650        else { /* we expect arrays at this level */
651            if (*s != '{') {
652                PyErr_SetString(PyExc_ValueError,
653                                "Subarray must start with a left brace");
654                Py_DECREF(result); return NULL;
655            }
656            do ++s; while (s != end && *s == ' ');
657            if (s == end) break; /* error */
658            stack[level++] = result;
659            if (!(result = PyList_New(0))) return NULL;
660        }
661    }
662    if (s == end || *s != '}') {
663        PyErr_SetString(PyExc_ValueError,
664                        "Unexpected end of array");
665        Py_DECREF(result); return NULL;
666    }
667    do ++s; while (s != end && *s == ' ');
668    if (s != end) {
669        PyErr_SetString(PyExc_ValueError,
670                        "Unexpected characters after end of array");
671        Py_DECREF(result); return NULL;
672    }
673    return result;
674}
675
676/* Cast string s with size and encoding to a Python tuple.
677   using the input and output syntax for composite types.
678   Use array of internal types or cast function or sequence of cast
679   functions to cast elements. The parameter len is the record size.
680   The parameter delim can specify a delimiter for the elements,
681   although composite types always use a comma as delimiter. */
682static PyObject *
683cast_record(char *s, Py_ssize_t size, int encoding,
684     int *type, PyObject *cast, Py_ssize_t len, char delim)
685{
686    PyObject *result, *ret;
687    char *end = s + size, *t;
688    Py_ssize_t i;
689
690    if (!delim) {
691        delim = ',';
692    }
693    else if (delim == '(' || delim ==')' || delim=='\\') {
694        PyErr_SetString(PyExc_ValueError, "Invalid record delimiter");
695        return NULL;
696    }
697
698    /* strip blanks at the beginning */
699    while (s != end && *s == ' ') ++s;
700    if (s == end || *s != '(') {
701        PyErr_SetString(PyExc_ValueError,
702                        "Record must start with a left parenthesis");
703        return NULL;
704    }
705    result = PyList_New(0);
706    if (!result) return NULL;
707    i = 0;
708    /* everything is set up, start parsing the record */
709    while (++s != end) {
710        PyObject *element;
711
712        if (*s == ')' || *s == delim) {
713            Py_INCREF(Py_None); element = Py_None;
714        }
715        else {
716            char *estr;
717            Py_ssize_t esize;
718            int quoted = 0, escaped = 0;
719
720            estr = s;
721            quoted = *s == '"';
722            if (quoted) ++s;
723            esize = 0;
724            while (s != end) {
725                if (!quoted && (*s == ')' || *s == delim))
726                    break;
727                if (*s == '"') {
728                    ++s; if (s == end) break;
729                    if (!(quoted && *s == '"')) {
730                        quoted = !quoted; continue;
731                    }
732                }
733                if (*s == '\\') {
734                    ++s; if (s == end) break;
735                }
736                ++s, ++esize;
737            }
738            if (s == end) break; /* error */
739            if (estr + esize != s) {
740                char *r;
741
742                escaped = 1;
743                /* create unescaped string */
744                t = estr;
745                estr = (char *) PyMem_Malloc(esize);
746                if (!estr) {
747                    Py_DECREF(result); return PyErr_NoMemory();
748                }
749                quoted = 0;
750                r = estr;
751                while (t != s) {
752                    if (*t == '"') {
753                        ++t;
754                        if (!(quoted && *t == '"')) {
755                            quoted = !quoted; continue;
756                        }
757                    }
758                    if (*t == '\\') ++t;
759                    *r++ = *t++;
760                }
761            }
762            if (type) { /* internal casting of element type */
763                int etype = type[i];
764
765                if (etype & PYGRES_ARRAY)
766                    element = cast_array(
767                        estr, esize, encoding, etype, NULL, 0);
768                else if (etype & PYGRES_TEXT)
769                    element = cast_sized_text(estr, esize, encoding, etype);
770                else
771                    element = cast_sized_simple(estr, esize, etype);
772            }
773            else { /* external casting of base type */
774#if IS_PY3
775                element = encoding == pg_encoding_ascii ? NULL :
776                    get_decoded_string(estr, esize, encoding);
777                if (!element) /* no decoding necessary or possible */
778#endif
779                element = PyBytes_FromStringAndSize(estr, esize);
780                if (element && cast) {
781                    if (len) {
782                        PyObject *ecast = PySequence_GetItem(cast, i);
783
784                        if (ecast) {
785                            if (ecast != Py_None) {
786                                PyObject *tmp = element;
787                                element = PyObject_CallFunctionObjArgs(
788                                    ecast, element, NULL);
789                                Py_DECREF(tmp);
790                            }
791                        }
792                        else {
793                            Py_DECREF(element); element = NULL;
794                        }
795                    }
796                    else {
797                        PyObject *tmp = element;
798                        element = PyObject_CallFunctionObjArgs(
799                            cast, element, NULL);
800                        Py_DECREF(tmp);
801                    }
802                }
803            }
804            if (escaped) PyMem_Free(estr);
805            if (!element) {
806                Py_DECREF(result); return NULL;
807            }
808        }
809        if (PyList_Append(result, element)) {
810            Py_DECREF(element); Py_DECREF(result); return NULL;
811        }
812        Py_DECREF(element);
813        if (len) ++i;
814        if (*s != delim) break; /* no next record */
815        if (len && i >= len) {
816            PyErr_SetString(PyExc_ValueError, "Too many columns");
817            Py_DECREF(result); return NULL;
818        }
819    }
820    if (s == end || *s != ')') {
821        PyErr_SetString(PyExc_ValueError, "Unexpected end of record");
822        Py_DECREF(result); return NULL;
823    }
824    do ++s; while (s != end && *s == ' ');
825    if (s != end) {
826        PyErr_SetString(PyExc_ValueError,
827                        "Unexpected characters after end of record");
828        Py_DECREF(result); return NULL;
829    }
830    if (len && i < len) {
831        PyErr_SetString(PyExc_ValueError, "Too few columns");
832        Py_DECREF(result); return NULL;
833    }
834
835    ret = PyList_AsTuple(result);
836    Py_DECREF(result);
837    return ret;
838}
839
840/* Cast string s with size and encoding to a Python dictionary.
841   using the input and output syntax for hstore values. */
842static PyObject *
843cast_hstore(char *s, Py_ssize_t size, int encoding)
844{
845    PyObject *result;
846    char *end = s + size;
847
848    result = PyDict_New();
849
850    /* everything is set up, start parsing the record */
851    while (s != end) {
852        char *key, *val;
853        PyObject *key_obj, *val_obj;
854        Py_ssize_t key_esc = 0, val_esc = 0, size;
855        int quoted;
856
857        while (s != end && *s == ' ') ++s;
858        if (s == end) break;
859        quoted = *s == '"';
860        if (quoted) {
861            key = ++s;
862            while (s != end) {
863                if (*s == '"') break;
864                if (*s == '\\') {
865                    if (++s == end) break;
866                    ++key_esc;
867                }
868                ++s;
869            }
870            if (s == end) {
871                PyErr_SetString(PyExc_ValueError, "Unterminated quote");
872                Py_DECREF(result); return NULL;
873            }
874        }
875        else {
876            key = s;
877            while (s != end) {
878                if (*s == '=' || *s == ' ') break;
879                if (*s == '\\') {
880                    if (++s == end) break;
881                    ++key_esc;
882                }
883                ++s;
884            }
885            if (s == key) {
886                PyErr_SetString(PyExc_ValueError, "Missing key");
887                Py_DECREF(result); return NULL;
888            }
889        }
890        size = s - key - key_esc;
891        if (key_esc) {
892            char *r = key, *t;
893            key = (char *) PyMem_Malloc(size);
894            if (!key) {
895                Py_DECREF(result); return PyErr_NoMemory();
896            }
897            t = key;
898            while (r != s) {
899                if (*r == '\\') {
900                    ++r; if (r == s) break;
901                }
902                *t++ = *r++;
903            }
904        }
905        key_obj = cast_sized_text(key, size, encoding, PYGRES_TEXT);
906        if (key_esc) PyMem_Free(key);
907        if (!key_obj) {
908            Py_DECREF(result); return NULL;
909        }
910        if (quoted) ++s;
911        while (s != end && *s == ' ') ++s;
912        if (s == end || *s++ != '=' || s == end || *s++ != '>') {
913            PyErr_SetString(PyExc_ValueError, "Invalid characters after key");
914            Py_DECREF(key_obj); Py_DECREF(result); return NULL;
915        }
916        while (s != end && *s == ' ') ++s;
917        quoted = *s == '"';
918        if (quoted) {
919            val = ++s;
920            while (s != end) {
921                if (*s == '"') break;
922                if (*s == '\\') {
923                    if (++s == end) break;
924                    ++val_esc;
925                }
926                ++s;
927            }
928            if (s == end) {
929                PyErr_SetString(PyExc_ValueError, "Unterminated quote");
930                Py_DECREF(result); return NULL;
931            }
932        }
933        else {
934            val = s;
935            while (s != end) {
936                if (*s == ',' || *s == ' ') break;
937                if (*s == '\\') {
938                    if (++s == end) break;
939                    ++val_esc;
940                }
941                ++s;
942            }
943            if (s == val) {
944                PyErr_SetString(PyExc_ValueError, "Missing value");
945                Py_DECREF(key_obj); Py_DECREF(result); return NULL;
946            }
947            if (STR_IS_NULL(val, s - val))
948                val = NULL;
949        }
950        if (val) {
951            size = s - val - val_esc;
952            if (val_esc) {
953                char *r = val, *t;
954                val = (char *) PyMem_Malloc(size);
955                if (!val) {
956                    Py_DECREF(key_obj); Py_DECREF(result);
957                    return PyErr_NoMemory();
958                }
959                t = val;
960                while (r != s) {
961                    if (*r == '\\') {
962                        ++r; if (r == s) break;
963                    }
964                    *t++ = *r++;
965                }
966            }
967            val_obj = cast_sized_text(val, size, encoding, PYGRES_TEXT);
968            if (val_esc) PyMem_Free(val);
969            if (!val_obj) {
970                Py_DECREF(key_obj); Py_DECREF(result); return NULL;
971            }
972        }
973        else {
974            Py_INCREF(Py_None); val_obj = Py_None;
975        }
976        if (quoted) ++s;
977        while (s != end && *s == ' ') ++s;
978        if (s != end) {
979            if (*s++ != ',') {
980                PyErr_SetString(PyExc_ValueError,
981                                "Invalid characters after val");
982                Py_DECREF(key_obj); Py_DECREF(val_obj);
983                Py_DECREF(result); return NULL;
984            }
985            while (s != end && *s == ' ') ++s;
986            if (s == end) {
987                PyErr_SetString(PyExc_ValueError, "Missing entry");
988                Py_DECREF(key_obj); Py_DECREF(val_obj);
989                Py_DECREF(result); return NULL;
990            }
991        }
992        PyDict_SetItem(result, key_obj, val_obj);
993        Py_DECREF(key_obj); Py_DECREF(val_obj);
994    }
995    return result;
996}
997
998/* Get appropriate error type from sqlstate. */
999static PyObject *
1000get_error_type(const char *sqlstate)
1001{
1002    switch (sqlstate[0]) {
1003        case '0':
1004            switch (sqlstate[1]) {
1005                case 'A':
1006                    return NotSupportedError;
1007            }
1008            break;
1009        case '2':
1010            switch (sqlstate[1]) {
1011                case '0':
1012                case '1':
1013                    return ProgrammingError;
1014                case '2':
1015                    return DataError;
1016                case '3':
1017                    return IntegrityError;
1018                case '4':
1019                case '5':
1020                    return InternalError;
1021                case '6':
1022                case '7':
1023                case '8':
1024                    return OperationalError;
1025                case 'B':
1026                case 'D':
1027                case 'F':
1028                    return InternalError;
1029            }
1030            break;
1031        case '3':
1032            switch (sqlstate[1]) {
1033                case '4':
1034                    return OperationalError;
1035                case '8':
1036                case '9':
1037                case 'B':
1038                    return InternalError;
1039                case 'D':
1040                case 'F':
1041                    return ProgrammingError;
1042            }
1043            break;
1044        case '4':
1045            switch (sqlstate[1]) {
1046                case '0':
1047                    return OperationalError;
1048                case '2':
1049                case '4':
1050                    return ProgrammingError;
1051            }
1052            break;
1053        case '5':
1054        case 'H':
1055            return OperationalError;
1056        case 'F':
1057        case 'P':
1058        case 'X':
1059            return InternalError;
1060    }
1061    return DatabaseError;
1062}
1063
1064/* Set database error message and sqlstate attribute. */
1065static void
1066set_error_msg_and_state(PyObject *type,
1067    const char *msg, int encoding, const char *sqlstate)
1068{
1069    PyObject *err_obj, *msg_obj, *sql_obj = NULL;
1070
1071#if IS_PY3
1072    if (encoding == -1) /* unknown */
1073        msg_obj = PyUnicode_DecodeLocale(msg, NULL);
1074    else
1075        msg_obj = get_decoded_string(msg, strlen(msg), encoding);
1076    if (!msg_obj) /* cannot decode */
1077#endif
1078    msg_obj = PyBytes_FromString(msg);
1079
1080    if (sqlstate) {
1081        sql_obj = PyStr_FromStringAndSize(sqlstate, 5);
1082    }
1083    else {
1084        Py_INCREF(Py_None); sql_obj = Py_None;
1085    }
1086
1087    err_obj = PyObject_CallFunctionObjArgs(type, msg_obj, NULL);
1088    if (err_obj) {
1089        Py_DECREF(msg_obj);
1090        PyObject_SetAttrString(err_obj, "sqlstate", sql_obj);
1091        Py_DECREF(sql_obj);
1092        PyErr_SetObject(type, err_obj);
1093        Py_DECREF(err_obj);
1094    }
1095    else {
1096        PyErr_SetString(type, msg);
1097    }
1098}
1099
1100/* Set given database error message. */
1101static void
1102set_error_msg(PyObject *type, const char *msg)
1103{
1104    set_error_msg_and_state(type, msg, pg_encoding_ascii, NULL);
1105}
1106
1107/* Set database error from connection and/or result. */
1108static void
1109set_error(PyObject *type, const char * msg, PGconn *cnx, PGresult *result)
1110{
1111    char *sqlstate = NULL;
1112    int encoding = pg_encoding_ascii;
1113
1114    if (cnx) {
1115        char *err_msg = PQerrorMessage(cnx);
1116        if (err_msg) {
1117            msg = err_msg;
1118            encoding = PQclientEncoding(cnx);
1119        }
1120    }
1121    if (result) {
1122        sqlstate = PQresultErrorField(result, PG_DIAG_SQLSTATE);
1123        if (sqlstate) type = get_error_type(sqlstate);
1124    }
1125
1126    set_error_msg_and_state(type, msg, encoding, sqlstate);
1127}
1128
1129#ifdef SSL_INFO
1130
1131/* Get SSL attributes and values as a dictionary. */
1132static PyObject *
1133get_ssl_attributes(PGconn *cnx) {
1134    PyObject *attr_dict = NULL;
1135    const char * const *s;
1136
1137    if (!(attr_dict = PyDict_New())) {
1138        return NULL;
1139    }
1140
1141    for (s = PQsslAttributeNames(cnx); *s; ++s) {
1142        const char *val = PQsslAttribute(cnx, *s);
1143
1144        if (val) {
1145            PyObject * val_obj = PyStr_FromString(val);
1146
1147            PyDict_SetItemString(attr_dict, *s, val_obj);
1148            Py_DECREF(val_obj);
1149        }
1150        else {
1151            PyDict_SetItemString(attr_dict, *s, Py_None);
1152        }
1153    }
1154
1155    return attr_dict;
1156}
1157
1158#endif /* SSL_INFO */
1159
1160/* Format result (mostly useful for debugging).
1161   Note: This is similar to the Postgres function PQprint().
1162   PQprint() is not used because handing over a stream from Python to
1163   PostgreSQL can be problematic if they use different libs for streams
1164   and because using PQprint() and tp_print is not recommended any more. */
1165static PyObject *
1166format_result(const PGresult *res)
1167{
1168    const int n = PQnfields(res);
1169
1170    if (n > 0) {
1171        char * const aligns = (char *) PyMem_Malloc(n * sizeof(char));
1172        int * const sizes = (int *) PyMem_Malloc(n * sizeof(int));
1173
1174        if (aligns && sizes) {
1175            const int m = PQntuples(res);
1176            int i, j;
1177            size_t size;
1178            char *buffer;
1179
1180            /* calculate sizes and alignments */
1181            for (j = 0; j < n; ++j) {
1182                const char * const s = PQfname(res, j);
1183                const int format = PQfformat(res, j);
1184
1185                sizes[j] = s ? (int) strlen(s) : 0;
1186                if (format) {
1187                    aligns[j] = '\0';
1188                    if (m && sizes[j] < 8)
1189                        /* "<binary>" must fit */
1190                        sizes[j] = 8;
1191                }
1192                else {
1193                    const Oid ftype = PQftype(res, j);
1194
1195                    switch (ftype) {
1196                        case INT2OID:
1197                        case INT4OID:
1198                        case INT8OID:
1199                        case FLOAT4OID:
1200                        case FLOAT8OID:
1201                        case NUMERICOID:
1202                        case OIDOID:
1203                        case XIDOID:
1204                        case CIDOID:
1205                        case CASHOID:
1206                            aligns[j] = 'r';
1207                            break;
1208                        default:
1209                            aligns[j] = 'l';
1210                    }
1211                }
1212            }
1213            for (i = 0; i < m; ++i) {
1214                for (j = 0; j < n; ++j) {
1215                    if (aligns[j]) {
1216                        const int k = PQgetlength(res, i, j);
1217
1218                        if (sizes[j] < k)
1219                            /* value must fit */
1220                            sizes[j] = k;
1221                    }
1222                }
1223            }
1224            size = 0;
1225            /* size of one row */
1226            for (j = 0; j < n; ++j) size += sizes[j] + 1;
1227            /* times number of rows incl. heading */
1228            size *= (m + 2);
1229            /* plus size of footer */
1230            size += 40;
1231            /* is the buffer size that needs to be allocated */
1232            buffer = (char *) PyMem_Malloc(size);
1233            if (buffer) {
1234                char *p = buffer;
1235                PyObject *result;
1236
1237                /* create the header */
1238                for (j = 0; j < n; ++j) {
1239                    const char * const s = PQfname(res, j);
1240                    const int k = sizes[j];
1241                    const int h = (k - (int) strlen(s)) / 2;
1242
1243                    sprintf(p, "%*s", h, "");
1244                    sprintf(p + h, "%-*s", k - h, s);
1245                    p += k;
1246                    if (j + 1 < n)
1247                        *p++ = '|';
1248                }
1249                *p++ = '\n';
1250                for (j = 0; j < n; ++j) {
1251                    int k = sizes[j];
1252
1253                    while (k--)
1254                        *p++ = '-';
1255                    if (j + 1 < n)
1256                        *p++ = '+';
1257                }
1258                *p++ = '\n';
1259                /* create the body */
1260                for (i = 0; i < m; ++i) {
1261                    for (j = 0; j < n; ++j) {
1262                        const char align = aligns[j];
1263                        const int k = sizes[j];
1264
1265                        if (align) {
1266                            sprintf(p, align == 'r' ? "%*s" : "%-*s", k,
1267                                    PQgetvalue(res, i, j));
1268                        }
1269                        else {
1270                            sprintf(p, "%-*s", k,
1271                                    PQgetisnull(res, i, j) ? "" : "<binary>");
1272                        }
1273                        p += k;
1274                        if (j + 1 < n)
1275                            *p++ = '|';
1276                    }
1277                    *p++ = '\n';
1278                }
1279                /* free memory */
1280                PyMem_Free(aligns); PyMem_Free(sizes);
1281                /* create the footer */
1282                sprintf(p, "(%d row%s)", m, m == 1 ? "" : "s");
1283                /* return the result */
1284                result = PyStr_FromString(buffer);
1285                PyMem_Free(buffer);
1286                return result;
1287            }
1288            else {
1289                PyMem_Free(aligns); PyMem_Free(sizes); return PyErr_NoMemory();
1290            }
1291        }
1292        else {
1293            PyMem_Free(aligns); PyMem_Free(sizes); return PyErr_NoMemory();
1294        }
1295    }
1296    else
1297        return PyStr_FromString("(nothing selected)");
1298}
1299
1300/* Internal function converting a Postgres datestyles to date formats. */
1301static const char *
1302date_style_to_format(const char *s)
1303{
1304    static const char *formats[] =
1305    {
1306        "%Y-%m-%d",  /* 0 = ISO */
1307        "%m-%d-%Y",  /* 1 = Postgres, MDY */
1308        "%d-%m-%Y",  /* 2 = Postgres, DMY */
1309        "%m/%d/%Y",  /* 3 = SQL, MDY */
1310        "%d/%m/%Y",  /* 4 = SQL, DMY */
1311        "%d.%m.%Y"   /* 5 = German */
1312    };
1313
1314    switch (s ? *s : 'I') {
1315        case 'P': /* Postgres */
1316            s = strchr(s + 1, ',');
1317            if (s) do ++s; while (*s && *s == ' ');
1318            return formats[s && *s == 'D' ? 2 : 1];
1319        case 'S': /* SQL */
1320            s = strchr(s + 1, ',');
1321            if (s) do ++s; while (*s && *s == ' ');
1322            return formats[s && *s == 'D' ? 4 : 3];
1323        case 'G': /* German */
1324            return formats[5];
1325        default: /* ISO */
1326            return formats[0]; /* ISO is the default */
1327    }
1328}
1329
1330/* Internal function converting a date format to a Postgres datestyle. */
1331static const char *
1332date_format_to_style(const char *s)
1333{
1334    static const char *datestyle[] =
1335    {
1336        "ISO, YMD",         /* 0 = %Y-%m-%d */
1337        "Postgres, MDY",    /* 1 = %m-%d-%Y */
1338        "Postgres, DMY",    /* 2 = %d-%m-%Y */
1339        "SQL, MDY",         /* 3 = %m/%d/%Y */
1340        "SQL, DMY",         /* 4 = %d/%m/%Y */
1341        "German, DMY"       /* 5 = %d.%m.%Y */
1342    };
1343
1344    switch (s ? s[1] : 'Y') {
1345        case 'm':
1346            switch (s[2]) {
1347                case '/':
1348                    return datestyle[3]; /* SQL, MDY */
1349                default:
1350                    return datestyle[1]; /* Postgres, MDY */
1351            }
1352        case 'd':
1353            switch (s[2]) {
1354                case '/':
1355                    return datestyle[4]; /* SQL, DMY */
1356                case '.':
1357                    return datestyle[5]; /* German */
1358                default:
1359                    return datestyle[2]; /* Postgres, DMY */
1360            }
1361        default:
1362            return datestyle[0]; /* ISO */
1363    }
1364}
1365
1366/* Internal wrapper for the notice receiver callback. */
1367static void
1368notice_receiver(void *arg, const PGresult *res)
1369{
1370    PyGILState_STATE gstate = PyGILState_Ensure();
1371    connObject *self = (connObject*) arg;
1372    PyObject *func = self->notice_receiver;
1373
1374    if (func) {
1375        noticeObject *notice = PyObject_NEW(noticeObject, &noticeType);
1376        PyObject *ret;
1377        if (notice) {
1378            notice->pgcnx = arg;
1379            notice->res = res;
1380        }
1381        else {
1382            Py_INCREF(Py_None);
1383            notice = (noticeObject *)(void *) Py_None;
1384        }
1385        ret = PyObject_CallFunction(func, "(O)", notice);
1386        Py_XDECREF(ret);
1387    }
1388    PyGILState_Release(gstate);
1389}
Note: See TracBrowser for help on using the repository browser.