Merge branch 'meta/travis'
[m6w6/ext-pq] / src / php_pqres.c
index a9ab9c7c562c67d733ff7f7f1b0a4cfcb0d9af24..c050898bcc46965f0829854bd7974449cfe4ceab 100644 (file)
 #include <php.h>
 
 #include <ext/spl/spl_iterators.h>
-#if HAVE_JSON
-#include <ext/json/php_json.h>
+#if PHP_PQ_HAVE_PHP_JSON_H
+#include <php_json.h> /* we've added the include directory to INCLUDES */
 #endif
+
 #include <libpq-events.h>
 
 #include "php_pq.h"
@@ -42,8 +43,8 @@ static zend_object_iterator *php_pqres_iterator_init(zend_class_entry *ce, zval
 
        iter = ecalloc(1, sizeof(*iter));
        iter->zi.funcs = &php_pqres_iterator_funcs;
-       iter->zi.data = object;
-       /* do not addref, because the iterator lives inside this object anyway */
+       iter->zi.data = zend_object_store_get_object(object TSRMLS_CC);
+       zend_objects_store_add_ref(object TSRMLS_CC);
 
        zfetch_type = prop = zend_read_property(ce, object, ZEND_STRL("fetchType"), 0 TSRMLS_CC);
        if (Z_TYPE_P(zfetch_type) != IS_LONG) {
@@ -66,22 +67,24 @@ static zend_object_iterator *php_pqres_iterator_init(zend_class_entry *ce, zval
 static void php_pqres_iterator_dtor(zend_object_iterator *i TSRMLS_DC)
 {
        php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
+       php_pqres_object_t *obj = i->data;
 
        if (iter->current_val) {
                zval_ptr_dtor(&iter->current_val);
                iter->current_val = NULL;
        }
+       zend_objects_store_del_ref_by_handle_ex(obj->zv.handle, obj->zv.handlers TSRMLS_CC);
        efree(iter);
 }
 
 static STATUS php_pqres_iterator_valid(zend_object_iterator *i TSRMLS_DC)
 {
        php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
-       php_pqres_object_t *obj = zend_object_store_get_object(iter->zi.data TSRMLS_CC);
+       php_pqres_object_t *obj = i->data;
 
        switch (PQresultStatus(obj->intern->res)) {
        case PGRES_TUPLES_OK:
-#if HAVE_PGRES_SINGLE_TUPLE
+#ifdef HAVE_PGRES_SINGLE_TUPLE
        case PGRES_SINGLE_TUPLE:
 #endif
                if (PQntuples(obj->intern->res) <= iter->index) {
@@ -95,6 +98,9 @@ static STATUS php_pqres_iterator_valid(zend_object_iterator *i TSRMLS_DC)
        return SUCCESS;
 }
 
+#define PHP_PQRES_JSON_OPTIONS(res) \
+       (php_pqres_fetch_type(res) != PHP_PQRES_FETCH_OBJECT ? PHP_JSON_OBJECT_AS_ARRAY:0)
+
 zval *php_pqres_typed_zval(php_pqres_t *res, char *val, size_t len, Oid typ TSRMLS_DC)
 {
        zval *zv, **zconv;
@@ -125,10 +131,9 @@ zval *php_pqres_typed_zval(php_pqres_t *res, char *val, size_t len, Oid typ TSRM
                }
                ZVAL_BOOL(zv, *val == 't');
                break;
-#if SIZEOF_LONG >= 8
+
        case PHP_PQ_OID_INT8:
        case PHP_PQ_OID_TID:
-#endif
        case PHP_PQ_OID_INT4:
        case PHP_PQ_OID_INT2:
        case PHP_PQ_OID_XID:
@@ -136,7 +141,21 @@ zval *php_pqres_typed_zval(php_pqres_t *res, char *val, size_t len, Oid typ TSRM
                if (!(res->auto_convert & PHP_PQRES_CONV_INT)) {
                        goto noconversion;
                }
-               ZVAL_LONG(zv, zend_atol(val, len));
+               {
+                       long lval;
+                       double dval;
+
+                       switch (is_numeric_string(val, len, &lval, &dval, 0)) {
+                               case IS_LONG:
+                                       ZVAL_LONG(zv, lval);
+                                       break;
+                               case IS_DOUBLE:
+                                       ZVAL_DOUBLE(zv, dval);
+                                       break;
+                               default:
+                                       goto noconversion;
+                       }
+               }
                break;
 
        case PHP_PQ_OID_FLOAT4:
@@ -151,31 +170,31 @@ zval *php_pqres_typed_zval(php_pqres_t *res, char *val, size_t len, Oid typ TSRM
                if (!(res->auto_convert & PHP_PQRES_CONV_DATETIME)) {
                        goto noconversion;
                }
-               php_pqdt_from_string(val, len, "Y-m-d", zv TSRMLS_CC);
+               php_pqdt_from_string(zv, NULL, val, len, "Y-m-d", NULL TSRMLS_CC);
                break;
 
        case PHP_PQ_OID_ABSTIME:
                if (!(res->auto_convert & PHP_PQRES_CONV_DATETIME)) {
                        goto noconversion;
                }
-               php_pqdt_from_string(val, len, "Y-m-d H:i:s", zv TSRMLS_CC);
+               php_pqdt_from_string(zv, NULL, val, len, "Y-m-d H:i:s", NULL TSRMLS_CC);
                break;
 
        case PHP_PQ_OID_TIMESTAMP:
                if (!(res->auto_convert & PHP_PQRES_CONV_DATETIME)) {
                        goto noconversion;
                }
-               php_pqdt_from_string(val, len, "Y-m-d H:i:s.u", zv TSRMLS_CC);
+               php_pqdt_from_string(zv, NULL, val, len, "Y-m-d H:i:s.u", NULL TSRMLS_CC);
                break;
 
        case PHP_PQ_OID_TIMESTAMPTZ:
                if (!(res->auto_convert & PHP_PQRES_CONV_DATETIME)) {
                        goto noconversion;
                }
-               php_pqdt_from_string(val, len, "Y-m-d H:i:s.uO", zv TSRMLS_CC);
+               php_pqdt_from_string(zv, NULL, val, len, "Y-m-d H:i:s.uO", NULL TSRMLS_CC);
                break;
 
-#if HAVE_JSON && defined(PHP_PQ_OID_JSON)
+#if PHP_PQ_HAVE_PHP_JSON_H && defined(PHP_PQ_OID_JSON)
 #      ifdef PHP_PQ_OID_JSONB
        case PHP_PQ_OID_JSONB:
 #      endif
@@ -183,7 +202,7 @@ zval *php_pqres_typed_zval(php_pqres_t *res, char *val, size_t len, Oid typ TSRM
                if (!(res->auto_convert & PHP_PQRES_CONV_JSON)) {
                        goto noconversion;
                }
-               php_json_decode_ex(zv, val, len, 0, 512 /* PHP_JSON_DEFAULT_DEPTH */ TSRMLS_CC);
+               php_json_decode_ex(zv, val, len, PHP_PQRES_JSON_OPTIONS(res), 512 /* PHP_JSON_DEFAULT_DEPTH */ TSRMLS_CC);
                break;
 #endif
 
@@ -288,7 +307,7 @@ zval *php_pqres_row_to_zval(PGresult *res, unsigned row, php_pqres_fetch_t fetch
 static void php_pqres_iterator_current(zend_object_iterator *i, zval ***data_ptr TSRMLS_DC)
 {
        php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
-       php_pqres_object_t *obj = zend_object_store_get_object(iter->zi.data TSRMLS_CC);
+       php_pqres_object_t *obj = i->data;
 
        if (!iter->current_val) {
                iter->current_val = php_pqres_row_to_zval(obj->intern->res, iter->index, iter->fetch_type, NULL TSRMLS_CC);
@@ -405,6 +424,11 @@ void php_pqres_init_instance_data(PGresult *res, php_pqconn_object_t *conn_obj,
        }
 }
 
+php_pqres_fetch_t php_pqres_fetch_type(php_pqres_t *res)
+{
+       return res->iter ? res->iter->fetch_type : res->default_fetch_type;
+}
+
 static void php_pqres_object_free(void *o TSRMLS_DC)
 {
        php_pqres_object_t *obj = o;
@@ -512,11 +536,7 @@ static void php_pqres_object_read_fetch_type(zval *object, void *o, zval *return
 {
        php_pqres_object_t *obj = o;
 
-       if (obj->intern->iter) {
-               RETVAL_LONG(obj->intern->iter->fetch_type);
-       } else {
-               RETVAL_LONG(obj->intern->default_fetch_type);
-       }
+       RETVAL_LONG(php_pqres_fetch_type(obj->intern));
 }
 
 static void php_pqres_object_write_fetch_type(zval *object, void *o, zval *value TSRMLS_DC)
@@ -686,7 +706,7 @@ static PHP_METHOD(pqres, bind) {
                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to bind column %s@%d", col.name, col.num);
                                        RETVAL_FALSE;
                                } else {
-                                       zend_hash_sort(&obj->intern->bound, zend_qsort, compare_index, 0 TSRMLS_CC);
+                                       zend_hash_sort(&obj->intern->bound, zend_qsort, php_pq_compare_index, 0 TSRMLS_CC);
                                        RETVAL_TRUE;
                                }
                        }
@@ -769,7 +789,7 @@ static PHP_METHOD(pqres, fetchRow) {
                        zval **row = NULL;
 
                        if (fetch_type == -1) {
-                                fetch_type = obj->intern->iter ? obj->intern->iter->fetch_type : obj->intern->default_fetch_type;
+                                fetch_type = php_pqres_fetch_type(obj->intern);
                        }
 
                        zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh TSRMLS_CC);
@@ -823,7 +843,7 @@ static PHP_METHOD(pqres, fetchCol) {
                        zval **row = NULL;
 
                        zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh TSRMLS_CC);
-                       php_pqres_iteration(getThis(), obj, obj->intern->iter ? obj->intern->iter->fetch_type : 0, &row TSRMLS_CC);
+                       php_pqres_iteration(getThis(), obj, php_pqres_fetch_type(obj->intern), &row TSRMLS_CC);
                        if (row) {
                                php_pqres_col_t col;
 
@@ -965,7 +985,7 @@ static PHP_METHOD(pqres, map) {
                        }
 
                        if (fetch_type == -1) {
-                               fetch_type = obj->intern->iter ? obj->intern->iter->fetch_type : obj->intern->default_fetch_type;
+                               fetch_type = php_pqres_fetch_type(obj->intern);
                        }
 
                        if (keys) {
@@ -1062,7 +1082,7 @@ static PHP_METHOD(pqres, fetchAll) {
                        int r, rows = PQntuples(obj->intern->res);
 
                        if (fetch_type == -1) {
-                                fetch_type = obj->intern->iter ? obj->intern->iter->fetch_type : obj->intern->default_fetch_type;
+                                fetch_type = php_pqres_fetch_type(obj->intern);
                        }
 
                        array_init(return_value);
@@ -1210,7 +1230,7 @@ PHP_MINIT_FUNCTION(pqres)
 #ifdef HAVE_PGRES_COPY_BOTH
        zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_BOTH"), PGRES_COPY_BOTH TSRMLS_CC);
 #endif
-#if HAVE_PGRES_SINGLE_TUPLE
+#ifdef HAVE_PGRES_SINGLE_TUPLE
        zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("SINGLE_TUPLE"), PGRES_SINGLE_TUPLE TSRMLS_CC);
 #endif
 
@@ -1224,7 +1244,7 @@ PHP_MINIT_FUNCTION(pqres)
        zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_SCALAR"), PHP_PQRES_CONV_SCALAR TSRMLS_CC);
        zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_ARRAY"), PHP_PQRES_CONV_ARRAY TSRMLS_CC);
        zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_DATETIME"), PHP_PQRES_CONV_DATETIME TSRMLS_CC);
-#if HAVE_JSON
+#if PHP_PQ_HAVE_PHP_JSON_H
        zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_JSON"), PHP_PQRES_CONV_JSON TSRMLS_CC);
 #endif
        zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_ALL"), PHP_PQRES_CONV_ALL TSRMLS_CC);