PHP-7.4 compat
[m6w6/ext-pq] / src / php_pqres.c
index f2ddf98029497a7d9314a1f82bde1d4a009f8cac..6e8bb0754ba75bab10c109c50c3882480405794f 100644 (file)
@@ -36,16 +36,14 @@ static zend_object_handlers php_pqres_object_handlers;
 static HashTable php_pqres_object_prophandlers;
 static zend_object_iterator_funcs php_pqres_iterator_funcs;
 
-static zend_object_iterator *php_pqres_iterator_init(zend_class_entry *ce, zval *object, int by_ref)
+static inline zend_object_iterator *php_pqres_iterator_init_ex(zend_class_entry *ce, zval *object, int by_ref)
 {
        php_pqres_iterator_t *iter;
        zval tmp, *zfetch_type;
 
        iter = ecalloc(1, sizeof(*iter));
        iter->zi.funcs = &php_pqres_iterator_funcs;
-       ZVAL_COPY(&iter->zi.data, object);
-
-       zend_iterator_init(&iter->zi);
+       ZVAL_COPY_VALUE(&iter->zi.data, object);
 
        zfetch_type = zend_read_property(ce, object, ZEND_STRL("fetchType"), 0, &tmp);
        iter->fetch_type = zval_get_long(zfetch_type);
@@ -55,30 +53,50 @@ static zend_object_iterator *php_pqres_iterator_init(zend_class_entry *ce, zval
        return (zend_object_iterator *) iter;
 }
 
+static zend_object_iterator *php_pqres_iterator_init(zend_class_entry *ce, zval *object, int by_ref)
+{
+       zend_object_iterator *iter = php_pqres_iterator_init_ex(ce, object, by_ref);
+
+       zend_iterator_init(iter);
+       Z_ADDREF_P(object);
+
+       return iter;
+}
 static void php_pqres_internal_iterator_init(zval *zobj)
 {
        php_pqres_object_t *obj = PHP_PQ_OBJ(zobj, NULL);
 
-       obj->intern->iter = (php_pqres_iterator_t *) php_pqres_iterator_init(Z_OBJCE_P(zobj), zobj, 0);
-       /* prevent cyclic dep */
-       Z_DELREF_P(zobj);
+       obj->intern->iter = (php_pqres_iterator_t *) php_pqres_iterator_init_ex(Z_OBJCE_P(zobj), zobj, 0);
        obj->intern->iter->zi.funcs->rewind((zend_object_iterator *) obj->intern->iter);
 
 }
 
-static void php_pqres_iterator_dtor(zend_object_iterator *i)
+static inline void php_pqres_iterator_dtor_ex(zend_object_iterator *i)
 {
        php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
 
 #if DBG_GC
-       fprintf(stderr, "FREE iter(#%d) %p\n", iter->zi.std.handle, iter);
+       fprintf(stderr, "FREE iter(#%d) rc=%d %p\n", iter->zi.std.handle, GC_REFCOUNT(&iter->zi.std), iter);
 #endif
        if (!Z_ISUNDEF(iter->current_val)) {
                zval_ptr_dtor(&iter->current_val);
                ZVAL_UNDEF(&iter->current_val);
        }
+}
+
+static void php_pqres_iterator_dtor(zend_object_iterator *i)
+{
+       php_pqres_iterator_dtor_ex(i);
        zval_ptr_dtor(&i->data);
-       zend_iterator_dtor(i);
+}
+
+static void php_pqres_internal_iterator_dtor(php_pqres_object_t *obj)
+{
+       if (obj->intern && obj->intern->iter) {
+               php_pqres_iterator_dtor_ex((zend_object_iterator *) obj->intern->iter);
+               efree(obj->intern->iter);
+               obj->intern->iter = NULL;
+       }
 }
 
 static ZEND_RESULT_CODE php_pqres_iterator_valid(zend_object_iterator *i)
@@ -145,7 +163,7 @@ zval *php_pqres_typed_zval(php_pqres_t *res, Oid typ, zval *zv)
                        goto noconversion;
                }
                {
-                       long lval;
+                       zend_long lval;
                        double dval;
 
                        switch (is_numeric_str_function(str, &lval, &dval)) {
@@ -374,7 +392,7 @@ static ZEND_RESULT_CODE php_pqres_count_elements(zval *object, long *count)
        }
 }
 
-ZEND_RESULT_CODE php_pqres_success(PGresult *res TSRMLS_DC)
+ZEND_RESULT_CODE php_pqres_success(PGresult *res)
 {
        zval zexc;
 
@@ -425,11 +443,7 @@ static void php_pqres_object_free(zend_object *o)
                        obj->intern->res = NULL;
                }
 
-               if (obj->intern->iter) {
-                       ZVAL_NULL(&obj->intern->iter->zi.data);
-                       php_pqres_iterator_dtor((zend_object_iterator *) obj->intern->iter);
-                       obj->intern->iter = NULL;
-               }
+               php_pqres_internal_iterator_dtor(obj);
 
                zend_hash_destroy(&obj->intern->bound);
                zend_hash_destroy(&obj->intern->converters);
@@ -477,6 +491,79 @@ static void php_pqres_object_read_error_message(zval *object, void *o, zval *ret
        }
 }
 
+static void php_pqres_object_read_diag(zval *object, void *o, zval *return_value)
+{
+       php_pqres_object_t *obj = o;
+       int i;
+       struct {
+               char code;
+               const char *const name;
+       } diag[] = {
+#ifdef PG_DIAG_SEVERITY
+                       {PG_DIAG_SEVERITY,                      "severity"},
+#endif
+#ifdef PG_DIAG_SQLSTATE
+                       {PG_DIAG_SQLSTATE,                      "sqlstate"},
+#endif
+#ifdef PG_DIAG_MESSAGE_PRIMARY
+                       {PG_DIAG_MESSAGE_PRIMARY,       "message_primary"},
+#endif
+#ifdef PG_DIAG_MESSAGE_DETAIL
+                       {PG_DIAG_MESSAGE_DETAIL,        "message_detail"},
+#endif
+#ifdef PG_DIAG_MESSAGE_HINT
+                       {PG_DIAG_MESSAGE_HINT,          "message_hint"},
+#endif
+#ifdef PG_DIAG_STATEMENT_POSITION
+                       {PG_DIAG_STATEMENT_POSITION,"statement_position"},
+#endif
+#ifdef PG_DIAG_INTERNAL_POSITION
+                       {PG_DIAG_INTERNAL_POSITION,     "internal_position"},
+#endif
+#ifdef PG_DIAG_INTERNAL_QUERY
+                       {PG_DIAG_INTERNAL_QUERY,        "internal_query"},
+#endif
+#ifdef PG_DIAG_CONTEXT
+                       {PG_DIAG_CONTEXT,                       "context"},
+#endif
+#ifdef PG_DIAG_SCHEMA_NAME
+                       {PG_DIAG_SCHEMA_NAME,           "schema_name"},
+#endif
+#ifdef PG_DIAG_TABLE_NAME
+                       {PG_DIAG_TABLE_NAME,            "table_name"},
+#endif
+#ifdef PG_DIAG_COLUMN_NAME
+                       {PG_DIAG_COLUMN_NAME,           "column_name"},
+#endif
+#ifdef PG_DIAG_DATATYPE_NAME
+                       {PG_DIAG_DATATYPE_NAME,         "datatype_name"},
+#endif
+#ifdef PG_DIAG_CONSTRAINT_NAME
+                       {PG_DIAG_CONSTRAINT_NAME,       "constraint_name"},
+#endif
+#ifdef PG_DIAG_SOURCE_FILE
+                       {PG_DIAG_SOURCE_FILE,           "source_file"},
+#endif
+#ifdef PG_DIAG_SOURCE_LINE
+                       {PG_DIAG_SOURCE_LINE,           "source_line"},
+#endif
+#ifdef PG_DIAG_SOURCE_FUNCTION
+                       {PG_DIAG_SOURCE_FUNCTION,       "source_function"},
+#endif
+       };
+
+       array_init_size(return_value, 32);
+       for (i = 0; i < sizeof(diag)/sizeof(diag[0]); ++i) {
+               char *value = PQresultErrorField(obj->intern->res, diag[i].code);
+
+               if (value) {
+                       add_assoc_string(return_value, diag[i].name, value);
+               } else {
+                       add_assoc_null(return_value, diag[i].name);
+               }
+       }
+}
+
 static void php_pqres_object_read_num_rows(zval *object, void *o, zval *return_value)
 {
        php_pqres_object_t *obj = o;
@@ -529,7 +616,7 @@ static void php_pqres_object_write_auto_conv(zval *object, void *o, zval *value)
        obj->intern->auto_convert = zval_get_long(value);
 }
 
-static ZEND_RESULT_CODE php_pqres_iteration(zval *zobj, php_pqres_object_t *obj, php_pqres_fetch_t fetch_type, zval *row TSRMLS_DC)
+static ZEND_RESULT_CODE php_pqres_iteration(zval *zobj, php_pqres_object_t *obj, php_pqres_fetch_t fetch_type, zval *row)
 {
        ZEND_RESULT_CODE rv;
        php_pqres_fetch_t orig_fetch;
@@ -561,7 +648,7 @@ typedef struct php_pqres_col {
 
 static ZEND_RESULT_CODE column_nn(php_pqres_object_t *obj, zval *zcol, php_pqres_col_t *col)
 {
-       long index = -1;
+       zend_long index = -1;
        char *name = NULL;
 
        if (!zcol) {
@@ -1105,13 +1192,13 @@ PHP_MINIT_FUNCTION(pqres)
        php_pqres_object_handlers.read_property = php_pq_object_read_prop;
        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_property_ptr_ptr = php_pq_object_get_prop_ptr_null;
        php_pqres_object_handlers.get_gc = php_pq_object_get_gc;
        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, 8, NULL, php_pq_object_prophandler_dtor, 1);
+       zend_hash_init(&php_pqres_object_prophandlers, 9, NULL, php_pq_object_prophandler_dtor, 1);
 
        zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("status"), ZEND_ACC_PUBLIC);
        ph.read = php_pqres_object_read_status;
@@ -1125,6 +1212,10 @@ PHP_MINIT_FUNCTION(pqres)
        ph.read = php_pqres_object_read_error_message;
        zend_hash_str_add_mem(&php_pqres_object_prophandlers, "errorMessage", sizeof("errorMessage")-1, (void *) &ph, sizeof(ph));
 
+       zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("diag"), ZEND_ACC_PUBLIC);
+       ph.read = php_pqres_object_read_diag;
+       zend_hash_str_add_mem(&php_pqres_object_prophandlers, "diag", sizeof("diag")-1, (void *) &ph, sizeof(ph));
+
        zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("numRows"), 0, ZEND_ACC_PUBLIC);
        ph.read = php_pqres_object_read_num_rows;
        zend_hash_str_add_mem(&php_pqres_object_prophandlers, "numRows", sizeof("numRows")-1, (void *) &ph, sizeof(ph));