Skip to content

Commit 25aae37

Browse files
committed
Fixed bug #64609 (pg_convert enum type support)
1 parent 79803be commit 25aae37

File tree

3 files changed

+69
-5
lines changed

3 files changed

+69
-5
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ PHP NEWS
1111
- PDO_pgsql:
1212
. Fixed bug #64949 (Buffer overflow in _pdo_pgsql_error). (Remi)
1313

14+
- pgsql:
15+
- Fixed bug #64609 (pg_convert enum type support). (Matteo)
16+
1417
?? ??? 2013, PHP 5.3.26
1518

1619
### DO NOT ADD ENTRIES HERE, ADD THEM ABOVE FOR 5.3.27 ###

ext/pgsql/pgsql.c

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4875,7 +4875,7 @@ PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, z
48754875
}
48764876

48774877
smart_str_appends(&querystr,
4878-
"SELECT a.attname, a.attnum, t.typname, a.attlen, a.attnotNULL, a.atthasdef, a.attndims "
4878+
"SELECT a.attname, a.attnum, t.typname, a.attlen, a.attnotnull, a.atthasdef, a.attndims, t.typtype = 'e' "
48794879
"FROM pg_class as c, pg_attribute a, pg_type t, pg_namespace n "
48804880
"WHERE a.attnum > 0 AND a.attrelid = c.oid AND c.relname = '");
48814881
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
49214921
add_assoc_bool(elem, "has default", 0);
49224922
}
49234923
add_assoc_long(elem, "array dims", atoi(PQgetvalue(pg_result,i,6)));
4924+
if (!strcmp(PQgetvalue(pg_result,i,7), "t")) {
4925+
add_assoc_bool(elem, "is enum", 1);
4926+
}
4927+
else {
4928+
add_assoc_bool(elem, "is enum", 0);
4929+
}
49244930
name = PQgetvalue(pg_result,i,0);
49254931
add_assoc_zval(meta, name, elem);
49264932
}
@@ -4954,7 +4960,18 @@ PHP_FUNCTION(pg_meta_data)
49544960
zval_dtor(return_value); /* destroy array */
49554961
RETURN_FALSE;
49564962
}
4957-
}
4963+
else {
4964+
HashPosition pos;
4965+
zval **val;
4966+
4967+
for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(return_value), &pos);
4968+
zend_hash_get_current_data_ex(Z_ARRVAL_P(return_value), (void **)&val, &pos) == SUCCESS;
4969+
zend_hash_move_forward_ex(Z_ARRVAL_P(return_value), &pos)) {
4970+
/* delete newly added entry, in order to keep BC */
4971+
zend_hash_del_key_or_index(Z_ARRVAL_PP(val), "is enum", sizeof("is enum"), 0, HASH_DEL_KEY);
4972+
}
4973+
}
4974+
}
49584975
/* }}} */
49594976

49604977
/* {{{ php_pgsql_get_data_type
@@ -5136,8 +5153,9 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con
51365153
char *field = NULL;
51375154
uint field_len = -1;
51385155
ulong num_idx = -1;
5139-
zval *meta, **def, **type, **not_null, **has_default, **val, *new_val;
5156+
zval *meta, **def, **type, **not_null, **has_default, **is_enum, **val, *new_val;
51405157
int new_len, key_type, err = 0, skip_field;
5158+
php_pgsql_data_type data_type;
51415159

51425160
assert(pg_link != NULL);
51435161
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
51885206
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected broken meta data. Missing 'has default'");
51895207
err = 1;
51905208
}
5209+
if (!err && zend_hash_find(Z_ARRVAL_PP(def), "is enum", sizeof("is enum"), (void **)&is_enum) == FAILURE) {
5210+
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected broken meta data. Missing 'is enum'");
5211+
err = 1;
5212+
}
51915213
if (!err && (Z_TYPE_PP(val) == IS_ARRAY ||
51925214
Z_TYPE_PP(val) == IS_OBJECT ||
51935215
Z_TYPE_PP(val) == IS_CONSTANT_ARRAY)) {
5194-
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects scaler values as field values");
5216+
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects scalar values as field values");
51955217
err = 1;
51965218
}
51975219
if (err) {
51985220
break; /* break out for() */
51995221
}
52005222
ALLOC_INIT_ZVAL(new_val);
5201-
switch(php_pgsql_get_data_type(Z_STRVAL_PP(type), Z_STRLEN_PP(type)))
5223+
5224+
if (Z_BVAL_PP(is_enum)) {
5225+
/* enums need to be treated like strings */
5226+
data_type = PG_TEXT;
5227+
}
5228+
else {
5229+
data_type = php_pgsql_get_data_type(Z_STRVAL_PP(type), Z_STRLEN_PP(type));
5230+
}
5231+
5232+
switch(data_type)
52025233
{
52035234
case PG_BOOL:
52045235
switch (Z_TYPE_PP(val)) {

ext/pgsql/tests/bug64609.phpt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--TEST--
2+
Bug #64609 (pg_convert enum type support)
3+
--SKIPIF--
4+
<?php
5+
include("skipif.inc");
6+
skip_server_version('8.3', '<');
7+
?>
8+
--FILE--
9+
<?php
10+
error_reporting(E_ALL);
11+
12+
include 'config.inc';
13+
14+
$db = pg_connect($conn_str);
15+
pg_query("BEGIN");
16+
pg_query("CREATE TYPE t_enum AS ENUM ('ok', 'ko')");
17+
pg_query("CREATE TABLE test_enum (a t_enum)");
18+
19+
$fields = array('a' => 'ok');
20+
$converted = pg_convert($db, 'test_enum', $fields);
21+
22+
pg_query("ROLLBACK");
23+
24+
var_dump($converted);
25+
?>
26+
--EXPECT--
27+
array(1) {
28+
["a"]=>
29+
string(4) "'ok'"
30+
}

0 commit comments

Comments
 (0)