|
50 | 50 | #define PGSQL_ASSOC 1<<0
|
51 | 51 | #define PGSQL_NUM 1<<1
|
52 | 52 | #define PGSQL_BOTH (PGSQL_ASSOC|PGSQL_NUM)
|
| 53 | +#define PGSQL_TYPED 1<<2 |
53 | 54 |
|
54 | 55 | #define PGSQL_NOTICE_LAST 1 /* Get the last notice */
|
55 | 56 | #define PGSQL_NOTICE_ALL 2 /* Get all notices */
|
|
61 | 62 | #define PGSQL_MAX_LENGTH_OF_LONG 30
|
62 | 63 | #define PGSQL_MAX_LENGTH_OF_DOUBLE 60
|
63 | 64 |
|
| 65 | +/* from postgresql/src/include/catalog/pg_type.h */ |
| 66 | +#define BOOLOID 16 |
| 67 | +#define BYTEAOID 17 |
| 68 | +#define INT2OID 21 |
| 69 | +#define INT4OID 23 |
| 70 | +#define INT8OID 20 |
| 71 | +#define TEXTOID 25 |
| 72 | +#define OIDOID 26 |
| 73 | +#define FLOAT4OID 700 |
| 74 | +#define FLOAT8OID 701 |
| 75 | + |
64 | 76 | #if ZEND_LONG_MAX < UINT_MAX
|
65 | 77 | #define PGSQL_RETURN_OID(oid) do { \
|
66 | 78 | if (oid > ZEND_LONG_MAX) { \
|
@@ -478,6 +490,7 @@ PHP_MINIT_FUNCTION(pgsql)
|
478 | 490 | REGISTER_LONG_CONSTANT("PGSQL_ASSOC", PGSQL_ASSOC, CONST_CS | CONST_PERSISTENT);
|
479 | 491 | REGISTER_LONG_CONSTANT("PGSQL_NUM", PGSQL_NUM, CONST_CS | CONST_PERSISTENT);
|
480 | 492 | REGISTER_LONG_CONSTANT("PGSQL_BOTH", PGSQL_BOTH, CONST_CS | CONST_PERSISTENT);
|
| 493 | + REGISTER_LONG_CONSTANT("PGSQL_TYPED", PGSQL_TYPED, CONST_CS | CONST_PERSISTENT); |
481 | 494 | /* For pg_last_notice() */
|
482 | 495 | REGISTER_LONG_CONSTANT("PGSQL_NOTICE_LAST", PGSQL_NOTICE_LAST, CONST_CS | CONST_PERSISTENT);
|
483 | 496 | REGISTER_LONG_CONSTANT("PGSQL_NOTICE_ALL", PGSQL_NOTICE_ALL, CONST_CS | CONST_PERSISTENT);
|
@@ -1846,6 +1859,72 @@ PHP_FUNCTION(pg_fetch_result)
|
1846 | 1859 | }
|
1847 | 1860 | /* }}} */
|
1848 | 1861 |
|
| 1862 | +/* {{{ void php_pgsql_get_field_value */ |
| 1863 | +static inline void php_pgsql_get_field_value(zval *value, PGresult *pgsql_result, zend_long result_type, int row, int column) |
| 1864 | +{ |
| 1865 | + if (PQgetisnull(pgsql_result, row, column)) { |
| 1866 | + ZVAL_NULL(value); |
| 1867 | + } else { |
| 1868 | + char *element = PQgetvalue(pgsql_result, row, column); |
| 1869 | + if (element) { |
| 1870 | + const size_t element_len = PQgetlength(pgsql_result, row, column); |
| 1871 | + Oid pgsql_type; |
| 1872 | + if (result_type & PGSQL_TYPED) { |
| 1873 | + pgsql_type = PQftype(pgsql_result, column); |
| 1874 | + } else { |
| 1875 | + pgsql_type = TEXTOID; |
| 1876 | + } |
| 1877 | + |
| 1878 | + switch (pgsql_type) { |
| 1879 | + case BOOLOID: |
| 1880 | + ZVAL_BOOL(value, *element == 't'); |
| 1881 | + break; |
| 1882 | + case FLOAT4OID: |
| 1883 | + case FLOAT8OID: |
| 1884 | + if (element_len == sizeof("Infinity") - 1 && strcmp(element, "Infinity") == 0) { |
| 1885 | + ZVAL_DOUBLE(value, ZEND_INFINITY); |
| 1886 | + } else if (element_len == sizeof("-Infinity") - 1 && strcmp(element, "-Infinity") == 0) { |
| 1887 | + ZVAL_DOUBLE(value, -ZEND_INFINITY); |
| 1888 | + } else if (element_len == sizeof("NaN") - 1 && strcmp(element, "NaN") == 0) { |
| 1889 | + ZVAL_DOUBLE(value, ZEND_NAN); |
| 1890 | + } else { |
| 1891 | + ZVAL_DOUBLE(value, zend_strtod(element, NULL)); |
| 1892 | + } |
| 1893 | + break; |
| 1894 | + case OIDOID: |
| 1895 | + case INT2OID: |
| 1896 | + case INT4OID: |
| 1897 | +#if SIZEOF_ZEND_LONG >= 8 |
| 1898 | + case INT8OID: |
| 1899 | +#endif |
| 1900 | + { |
| 1901 | + zend_long long_value = ZEND_ATOL(element); |
| 1902 | + ZVAL_LONG(value, long_value); |
| 1903 | + break; |
| 1904 | + } |
| 1905 | + case BYTEAOID: |
| 1906 | + { |
| 1907 | + size_t tmp_len; |
| 1908 | + char *tmp_ptr = (char *)PQunescapeBytea((unsigned char *)element, &tmp_len); |
| 1909 | + if (!tmp_ptr) { |
| 1910 | + /* PQunescapeBytea returned an error */ |
| 1911 | + ZVAL_NULL(value); |
| 1912 | + } else { |
| 1913 | + ZVAL_STRINGL(value, tmp_ptr, tmp_len); |
| 1914 | + PQfreemem(tmp_ptr); |
| 1915 | + } |
| 1916 | + break; |
| 1917 | + } |
| 1918 | + default: |
| 1919 | + ZVAL_STRINGL(value, element, element_len); |
| 1920 | + } |
| 1921 | + } else { |
| 1922 | + ZVAL_NULL(value); |
| 1923 | + } |
| 1924 | + } |
| 1925 | +} |
| 1926 | +/* }}} */ |
| 1927 | + |
1849 | 1928 | /* {{{ void php_pgsql_fetch_hash */
|
1850 | 1929 | static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, zend_long result_type, int into_object)
|
1851 | 1930 | {
|
@@ -1906,28 +1985,17 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, zend_long result_
|
1906 | 1985 |
|
1907 | 1986 | array_init(return_value);
|
1908 | 1987 | for (i = 0, num_fields = PQnfields(pgsql_result); i < num_fields; i++) {
|
1909 |
| - if (PQgetisnull(pgsql_result, pgsql_row, i)) { |
1910 |
| - if (result_type & PGSQL_NUM) { |
1911 |
| - add_index_null(return_value, i); |
1912 |
| - } |
1913 |
| - if (result_type & PGSQL_ASSOC) { |
1914 |
| - field_name = PQfname(pgsql_result, i); |
1915 |
| - add_assoc_null(return_value, field_name); |
1916 |
| - } |
1917 |
| - } else { |
1918 |
| - char *element = PQgetvalue(pgsql_result, pgsql_row, i); |
1919 |
| - if (element) { |
1920 |
| - const size_t element_len = strlen(element); |
1921 |
| - |
1922 |
| - if (result_type & PGSQL_NUM) { |
1923 |
| - add_index_stringl(return_value, i, element, element_len); |
1924 |
| - } |
| 1988 | + if (result_type & PGSQL_NUM) { |
| 1989 | + zval value; |
| 1990 | + php_pgsql_get_field_value(&value, pgsql_result, result_type, pgsql_row, i); |
| 1991 | + add_index_zval(return_value, i, &value); |
| 1992 | + } |
1925 | 1993 |
|
1926 |
| - if (result_type & PGSQL_ASSOC) { |
1927 |
| - field_name = PQfname(pgsql_result, i); |
1928 |
| - add_assoc_stringl(return_value, field_name, element, element_len); |
1929 |
| - } |
1930 |
| - } |
| 1994 | + if (result_type & PGSQL_ASSOC) { |
| 1995 | + zval value; |
| 1996 | + php_pgsql_get_field_value(&value, pgsql_result, result_type, pgsql_row, i); |
| 1997 | + field_name = PQfname(pgsql_result, i); |
| 1998 | + add_assoc_zval(return_value, field_name, &value); |
1931 | 1999 | }
|
1932 | 2000 | }
|
1933 | 2001 |
|
@@ -5788,25 +5856,16 @@ PHP_PGSQL_API void php_pgsql_result2array(PGresult *pg_result, zval *ret_array,
|
5788 | 5856 | for (pg_row = 0; pg_row < pg_numrows; pg_row++) {
|
5789 | 5857 | array_init(&row);
|
5790 | 5858 | for (i = 0, num_fields = PQnfields(pg_result); i < num_fields; i++) {
|
5791 |
| - field_name = PQfname(pg_result, i); |
5792 |
| - if (PQgetisnull(pg_result, pg_row, i)) { |
5793 |
| - if (result_type & PGSQL_ASSOC) { |
5794 |
| - add_assoc_null(&row, field_name); |
5795 |
| - } |
5796 |
| - if (result_type & PGSQL_NUM) { |
5797 |
| - add_next_index_null(&row); |
5798 |
| - } |
5799 |
| - } else { |
5800 |
| - char *element = PQgetvalue(pg_result, pg_row, i); |
5801 |
| - if (element) { |
5802 |
| - const size_t element_len = strlen(element); |
5803 |
| - if (result_type & PGSQL_ASSOC) { |
5804 |
| - add_assoc_stringl(&row, field_name, element, element_len); |
5805 |
| - } |
5806 |
| - if (result_type & PGSQL_NUM) { |
5807 |
| - add_next_index_stringl(&row, element, element_len); |
5808 |
| - } |
5809 |
| - } |
| 5859 | + if (result_type & PGSQL_ASSOC) { |
| 5860 | + zval value; |
| 5861 | + php_pgsql_get_field_value(&value, pg_result, result_type, pg_row, i); |
| 5862 | + field_name = PQfname(pg_result, i); |
| 5863 | + add_assoc_zval(&row, field_name, &value); |
| 5864 | + } |
| 5865 | + if (result_type & PGSQL_NUM) { |
| 5866 | + zval value; |
| 5867 | + php_pgsql_get_field_value(&value, pg_result, result_type, pg_row, i); |
| 5868 | + add_next_index_zval(&row, &value); |
5810 | 5869 | }
|
5811 | 5870 | }
|
5812 | 5871 | add_index_zval(ret_array, pg_row, &row);
|
|
0 commit comments