array parser
[m6w6/ext-pq] / src / php_pqres.c
index a1e1d0022eb63d2393f6c6ad6dcfc6cd8bc2f6a7..2ebcf74dbc2a2944d32855eb9081ce212f1e7f43 100644 (file)
@@ -126,20 +126,79 @@ zval *php_pqres_row_to_zval(PGresult *res, unsigned row, php_pqres_fetch_t fetch
                                        break;
                                }
                        } else {
+                               zval *zv;
+                               Oid typ = PQftype(res, c);
                                char *val = PQgetvalue(res, row, c);
                                int len = PQgetlength(res, row, c);
 
+                               MAKE_STD_ZVAL(zv);
+
+                               switch (typ) {
+#ifdef HAVE_PHP_PQ_TYPE_H
+#      undef PHP_PQ_TYPE
+#      include "php_pq_type.h"
+                               case PHP_PQ_OID_BOOL:
+                                       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:
+                               case PHP_PQ_OID_OID:
+                                       ZVAL_LONG(zv, zend_atol(val, len));
+                                       break;
+
+                               case PHP_PQ_OID_FLOAT4:
+                               case PHP_PQ_OID_FLOAT8:
+                                       ZVAL_DOUBLE(zv, zend_strtod(val, NULL));
+                                       break;
+
+                               case PHP_PQ_OID_DATE:
+                                       php_pqdt_from_string(val, len, "Y-m-d", zv TSRMLS_CC);
+                                       break;
+
+                               case PHP_PQ_OID_ABSTIME:
+                                       php_pqdt_from_string(val, len, "Y-m-d H:i:s", zv TSRMLS_CC);
+                                       break;
+
+                               case PHP_PQ_OID_TIMESTAMP:
+                                       php_pqdt_from_string(val, len, "Y-m-d H:i:s.u", zv TSRMLS_CC);
+                                       break;
+
+                               case PHP_PQ_OID_TIMESTAMPTZ:
+                                       php_pqdt_from_string(val, len, "Y-m-d H:i:s.uO", zv TSRMLS_CC);
+                                       break;
+
+
+#else
+                               case 16: /* BOOL */
+                                       ZVAL_BOOL(zv, *val == 't');
+                                       break;
+#endif
+                               default:
+                                       if (PHP_PQ_TYPE_IS_ARRAY(typ) && (Z_ARRVAL_P(zv) = php_pq_parse_array(val, len TSRMLS_CC))) {
+                                               Z_TYPE_P(zv) = IS_ARRAY;
+                                       } else {
+                                               ZVAL_STRINGL(zv, val, len, 1);
+                                       }
+                                       break;
+                               }
+
                                switch (fetch_type) {
                                case PHP_PQRES_FETCH_OBJECT:
-                                       add_property_stringl(data, PQfname(res, c), val, len, 1);
+                                       add_property_zval(data, PQfname(res, c), zv);
+                                       zval_ptr_dtor(&zv);
                                        break;
 
                                case PHP_PQRES_FETCH_ASSOC:
-                                       add_assoc_stringl(data, PQfname(res, c), val, len, 1);
+                                       add_assoc_zval(data, PQfname(res, c), zv);
                                        break;
 
                                case PHP_PQRES_FETCH_ARRAY:
-                                       add_index_stringl(data, c, val, len ,1);
+                                       add_index_zval(data, c, zv);
                                        break;
                                }
                        }
@@ -441,6 +500,10 @@ static STATUS column_nn(php_pqres_object_t *obj, zval *zcol, php_pqres_col_t *co
        char *name = NULL;
 
        switch (Z_TYPE_P(zcol)) {
+       case IS_LONG:
+               index = Z_LVAL_P(zcol);
+               break;
+
        default:
                convert_to_string(zcol);
                /* no break */
@@ -450,10 +513,6 @@ static STATUS column_nn(php_pqres_object_t *obj, zval *zcol, php_pqres_col_t *co
                        name = Z_STRVAL_P(zcol);
                }
                break;
-
-       case IS_LONG:
-               index = Z_LVAL_P(zcol);
-               break;
        }
 
        if (name) {
@@ -614,16 +673,17 @@ static zval **column_at(zval *row, int col TSRMLS_DC)
        return data;
 }
 
-ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_col, 0, 0, 0)
-       ZEND_ARG_INFO(0, col_num)
+ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_col, 0, 0, 2)
+       ZEND_ARG_INFO(0, col)
+       ZEND_ARG_INFO(1, ref)
 ZEND_END_ARG_INFO();
 static PHP_METHOD(pqres, fetchCol) {
        zend_error_handling zeh;
-       long fetch_col = 0;
+       zval *zcol, *zref;
        STATUS rv;
 
        zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
-       rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &fetch_col);
+       rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/z", &zcol, &zref);
        zend_restore_error_handling(&zeh TSRMLS_CC);
 
        if (SUCCESS == rv) {
@@ -636,11 +696,23 @@ static PHP_METHOD(pqres, fetchCol) {
 
                        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);
-                       if (row) {
-                               zval **col = column_at(*row, fetch_col TSRMLS_CC);
+                       if (!row) {
+                               RETVAL_FALSE;
+                       } else {
+                               php_pqres_col_t col;
 
-                               if (col) {
-                                       RETVAL_ZVAL(*col, 1, 0);
+                               if (SUCCESS != column_nn(obj, zcol, &col TSRMLS_CC)) {
+                                       RETVAL_FALSE;
+                               } else {
+                                       zval **zres = column_at(*row, col.num TSRMLS_CC);
+
+                                       if (!zres) {
+                                               RETVAL_FALSE;
+                                       } else {
+                                               zval_dtor(zref);
+                                               ZVAL_ZVAL(zref, *zres, 1, 1);
+                                               RETVAL_TRUE;
+                                       }
                                }
                        }
                        zend_restore_error_handling(&zeh TSRMLS_CC);
@@ -879,7 +951,9 @@ PHP_MINIT_FUNCTION(pqres)
        php_pqres_object_handlers.write_property = php_pq_object_write_prop;
        php_pqres_object_handlers.clone_obj = NULL;
        php_pqres_object_handlers.get_property_ptr_ptr = NULL;
+       php_pqres_object_handlers.get_gc = NULL;
        php_pqres_object_handlers.get_debug_info = php_pq_object_debug_info;
+       php_pqres_object_handlers.get_properties = php_pq_object_properties;
        php_pqres_object_handlers.count_elements = php_pqres_count_elements;
 
        zend_hash_init(&php_pqres_object_prophandlers, 6, NULL, NULL, 1);