From 25aae37229a439109c020150d0f496ef4a237ecd Mon Sep 17 00:00:00 2001 From: Matteo Beccati Date: Sun, 2 Jun 2013 06:29:35 +0200 Subject: [PATCH] Fixed bug #64609 (pg_convert enum type support) --- NEWS | 3 +++ ext/pgsql/pgsql.c | 41 ++++++++++++++++++++++++++++++----- ext/pgsql/tests/bug64609.phpt | 30 +++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 ext/pgsql/tests/bug64609.phpt diff --git a/NEWS b/NEWS index 7889832ab6..a1fbbcdaf6 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,9 @@ PHP NEWS - PDO_pgsql: . Fixed bug #64949 (Buffer overflow in _pdo_pgsql_error). (Remi) +- pgsql: + - Fixed bug #64609 (pg_convert enum type support). (Matteo) + ?? ??? 2013, PHP 5.3.26 ### DO NOT ADD ENTRIES HERE, ADD THEM ABOVE FOR 5.3.27 ### diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index a0faed1424..c5d9a4ab1c 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -4875,7 +4875,7 @@ PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, z } smart_str_appends(&querystr, - "SELECT a.attname, a.attnum, t.typname, a.attlen, a.attnotNULL, a.atthasdef, a.attndims " + "SELECT a.attname, a.attnum, t.typname, a.attlen, a.attnotnull, a.atthasdef, a.attndims, t.typtype = 'e' " "FROM pg_class as c, pg_attribute a, pg_type t, pg_namespace n " "WHERE a.attnum > 0 AND a.attrelid = c.oid AND c.relname = '"); tmp_name2 = php_addslashes(tmp_name2, strlen(tmp_name2), &new_len, 0 TSRMLS_CC); @@ -4921,6 +4921,12 @@ PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, z add_assoc_bool(elem, "has default", 0); } add_assoc_long(elem, "array dims", atoi(PQgetvalue(pg_result,i,6))); + if (!strcmp(PQgetvalue(pg_result,i,7), "t")) { + add_assoc_bool(elem, "is enum", 1); + } + else { + add_assoc_bool(elem, "is enum", 0); + } name = PQgetvalue(pg_result,i,0); add_assoc_zval(meta, name, elem); } @@ -4954,7 +4960,18 @@ PHP_FUNCTION(pg_meta_data) zval_dtor(return_value); /* destroy array */ RETURN_FALSE; } -} + else { + HashPosition pos; + zval **val; + + for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(return_value), &pos); + zend_hash_get_current_data_ex(Z_ARRVAL_P(return_value), (void **)&val, &pos) == SUCCESS; + zend_hash_move_forward_ex(Z_ARRVAL_P(return_value), &pos)) { + /* delete newly added entry, in order to keep BC */ + zend_hash_del_key_or_index(Z_ARRVAL_PP(val), "is enum", sizeof("is enum"), 0, HASH_DEL_KEY); + } + } +} /* }}} */ /* {{{ php_pgsql_get_data_type @@ -5136,8 +5153,9 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con char *field = NULL; uint field_len = -1; ulong num_idx = -1; - zval *meta, **def, **type, **not_null, **has_default, **val, *new_val; + zval *meta, **def, **type, **not_null, **has_default, **is_enum, **val, *new_val; int new_len, key_type, err = 0, skip_field; + php_pgsql_data_type data_type; assert(pg_link != NULL); assert(Z_TYPE_P(values) == IS_ARRAY); @@ -5188,17 +5206,30 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected broken meta data. Missing 'has default'"); err = 1; } + if (!err && zend_hash_find(Z_ARRVAL_PP(def), "is enum", sizeof("is enum"), (void **)&is_enum) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected broken meta data. Missing 'is enum'"); + err = 1; + } if (!err && (Z_TYPE_PP(val) == IS_ARRAY || Z_TYPE_PP(val) == IS_OBJECT || Z_TYPE_PP(val) == IS_CONSTANT_ARRAY)) { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects scaler values as field values"); + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects scalar values as field values"); err = 1; } if (err) { break; /* break out for() */ } ALLOC_INIT_ZVAL(new_val); - switch(php_pgsql_get_data_type(Z_STRVAL_PP(type), Z_STRLEN_PP(type))) + + if (Z_BVAL_PP(is_enum)) { + /* enums need to be treated like strings */ + data_type = PG_TEXT; + } + else { + data_type = php_pgsql_get_data_type(Z_STRVAL_PP(type), Z_STRLEN_PP(type)); + } + + switch(data_type) { case PG_BOOL: switch (Z_TYPE_PP(val)) { diff --git a/ext/pgsql/tests/bug64609.phpt b/ext/pgsql/tests/bug64609.phpt new file mode 100644 index 0000000000..0df63012da --- /dev/null +++ b/ext/pgsql/tests/bug64609.phpt @@ -0,0 +1,30 @@ +--TEST-- +Bug #64609 (pg_convert enum type support) +--SKIPIF-- + +--FILE-- + 'ok'); +$converted = pg_convert($db, 'test_enum', $fields); + +pg_query("ROLLBACK"); + +var_dump($converted); +?> +--EXPECT-- +array(1) { + ["a"]=> + string(4) "'ok'" +} -- 2.40.0