Skip to content

Commit f26047f

Browse files
committed
Don't store resolved pgsql field/table oids as resources
Store these in hash tables indexed by oid. This is simpler and more efficient, as we don't need to create resources or hash keys.
1 parent 01b71f4 commit f26047f

File tree

2 files changed

+65
-92
lines changed

2 files changed

+65
-92
lines changed

ext/pgsql/pgsql.c

Lines changed: 63 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ ZEND_TSRMLS_CACHE_DEFINE()
112112
ZEND_GET_MODULE(pgsql)
113113
#endif
114114

115-
static int le_link, le_plink, le_result, le_lofp, le_string;
115+
static int le_link, le_plink, le_result, le_lofp;
116116

117117
/* Compatibility definitions */
118118

@@ -278,9 +278,9 @@ static void _free_result(zend_resource *rsrc)
278278
}
279279
/* }}} */
280280

281-
static void release_string(zend_resource *rsrc)
281+
static void release_string(zval *zv)
282282
{
283-
zend_string_release((zend_string *) rsrc->ptr);
283+
zend_string_release((zend_string *) Z_PTR_P(zv));
284284
}
285285

286286
static bool _php_pgsql_identifier_is_escaped(const char *identifier, size_t len) /* {{{ */
@@ -356,7 +356,6 @@ PHP_MINIT_FUNCTION(pgsql)
356356
le_plink = zend_register_list_destructors_ex(NULL, _close_pgsql_plink, "pgsql link persistent", module_number);
357357
le_result = zend_register_list_destructors_ex(_free_result, NULL, "pgsql result", module_number);
358358
le_lofp = zend_register_list_destructors_ex(_free_ptr, NULL, "pgsql large object", module_number);
359-
le_string = zend_register_list_destructors_ex(release_string, NULL, "pgsql string", module_number);
360359
/* libpq version */
361360
php_libpq_version(buf, sizeof(buf));
362361
REGISTER_STRING_CONSTANT("PGSQL_LIBPQ_VERSION", buf, CONST_CS | CONST_PERSISTENT);
@@ -480,6 +479,8 @@ PHP_RINIT_FUNCTION(pgsql)
480479
{
481480
PGG(default_link) = NULL;
482481
PGG(num_links) = PGG(num_persistent);
482+
zend_hash_init(&PGG(field_oids), 0, NULL, release_string, 0);
483+
zend_hash_init(&PGG(table_oids), 0, NULL, release_string, 0);
483484
return SUCCESS;
484485
}
485486
/* }}} */
@@ -490,6 +491,8 @@ PHP_RSHUTDOWN_FUNCTION(pgsql)
490491
/* clean up notice messages */
491492
zend_hash_clean(&PGG(notices));
492493
zend_hash_clean(&PGG(hashes));
494+
zend_hash_destroy(&PGG(field_oids));
495+
zend_hash_destroy(&PGG(table_oids));
493496
/* clean up persistent connection */
494497
zend_hash_apply(&EG(persistent_list), (apply_func_t) _rollback_transactions);
495498
return SUCCESS;
@@ -1481,61 +1484,47 @@ static inline bool is_valid_oid_string(zend_string *oid, Oid *return_oid)
14811484
}
14821485

14831486
/* {{{ get_field_name */
1484-
static zend_string *get_field_name(PGconn *pgsql, Oid oid, HashTable *list)
1487+
static zend_string *get_field_name(PGconn *pgsql, Oid oid)
14851488
{
1486-
smart_str str = {0};
1487-
zend_resource *field_type;
1488-
zend_string *ret = NULL;
1489+
zend_string *ret = zend_hash_index_find_ptr(&PGG(field_oids), oid);
1490+
if (ret) {
1491+
zend_string_addref(ret);
1492+
return ret;
1493+
}
14891494

1490-
/* try to lookup the type in the resource list */
1491-
smart_str_appends(&str, "pgsql_oid_");
1492-
smart_str_append_unsigned(&str, oid);
1493-
smart_str_0(&str);
1495+
PGresult *result = PQexec(pgsql, "select oid,typname from pg_type");
1496+
if (!result || PQresultStatus(result) != PGRES_TUPLES_OK) {
1497+
if (result) {
1498+
PQclear(result);
1499+
}
1500+
return ZSTR_EMPTY_ALLOC();
1501+
}
14941502

1495-
if ((field_type = zend_hash_find_ptr(list, str.s)) != NULL) {
1496-
ret = zend_string_copy((zend_string *) field_type->ptr);
1497-
} else { /* hash all oid's */
1498-
int i, num_rows;
1499-
int oid_offset,name_offset;
1500-
char *tmp_oid, *end_ptr, *tmp_name;
1501-
zend_resource new_oid_entry;
1502-
PGresult *result;
1503-
1504-
if ((result = PQexec(pgsql, "select oid,typname from pg_type")) == NULL || PQresultStatus(result) != PGRES_TUPLES_OK) {
1505-
if (result) {
1506-
PQclear(result);
1507-
}
1508-
smart_str_free(&str);
1509-
return ZSTR_EMPTY_ALLOC();
1503+
int num_rows = PQntuples(result);
1504+
int oid_offset = PQfnumber(result,"oid");
1505+
int name_offset = PQfnumber(result,"typname");
1506+
for (int i = 0; i < num_rows; i++) {
1507+
char *tmp_oid_str = PQgetvalue(result, i, oid_offset);
1508+
if (!tmp_oid_str) {
1509+
continue;
15101510
}
1511-
num_rows = PQntuples(result);
1512-
oid_offset = PQfnumber(result,"oid");
1513-
name_offset = PQfnumber(result,"typname");
15141511

1515-
for (i=0; i<num_rows; i++) {
1516-
if ((tmp_oid = PQgetvalue(result,i,oid_offset))==NULL) {
1517-
continue;
1518-
}
1512+
char *tmp_name = PQgetvalue(result, i, name_offset);
1513+
if (!tmp_name) {
1514+
continue;
1515+
}
15191516

1520-
smart_str_free(&str);
1521-
smart_str_appends(&str, "pgsql_oid_");
1522-
smart_str_appends(&str, tmp_oid);
1523-
smart_str_0(&str);
1517+
char *end_ptr;
1518+
Oid tmp_oid = strtoul(tmp_oid_str, &end_ptr, 10);
15241519

1525-
if ((tmp_name = PQgetvalue(result,i,name_offset))==NULL) {
1526-
continue;
1527-
}
1528-
new_oid_entry.type = le_string;
1529-
new_oid_entry.ptr = zend_string_init(tmp_name, strlen(tmp_name), 0);
1530-
zend_hash_update_mem(list, str.s, (void *) &new_oid_entry, sizeof(zend_resource));
1531-
if (!ret && strtoul(tmp_oid, &end_ptr, 10)==oid) {
1532-
ret = zend_string_copy(new_oid_entry.ptr);
1533-
}
1520+
zend_string *name = zend_string_init(tmp_name, strlen(tmp_name), 0);
1521+
zend_hash_index_update_ptr(&PGG(field_oids), tmp_oid, name);
1522+
if (!ret && tmp_oid == oid) {
1523+
ret = zend_string_copy(name);
15341524
}
1535-
PQclear(result);
15361525
}
15371526

1538-
smart_str_free(&str);
1527+
PQclear(result);
15391528
return ret;
15401529
}
15411530
/* }}} */
@@ -1547,10 +1536,6 @@ PHP_FUNCTION(pg_field_table)
15471536
pgsql_result_handle *pg_result;
15481537
zend_long fnum = -1;
15491538
bool return_oid = 0;
1550-
Oid oid;
1551-
smart_str hash_key = {0};
1552-
char *table_name;
1553-
zend_resource *field_table;
15541539

15551540
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl|b", &result, &fnum, &return_oid) == FAILURE) {
15561541
RETURN_THROWS();
@@ -1570,8 +1555,7 @@ PHP_FUNCTION(pg_field_table)
15701555
RETURN_THROWS();
15711556
}
15721557

1573-
oid = PQftable(pg_result->result, (int)fnum);
1574-
1558+
Oid oid = PQftable(pg_result->result, (int)fnum);
15751559
if (InvalidOid == oid) {
15761560
RETURN_FALSE;
15771561
}
@@ -1580,49 +1564,37 @@ PHP_FUNCTION(pg_field_table)
15801564
PGSQL_RETURN_OID(oid);
15811565
}
15821566

1583-
/* try to lookup the table name in the resource list */
1584-
smart_str_appends(&hash_key, "pgsql_table_oid_");
1585-
smart_str_append_unsigned(&hash_key, oid);
1586-
smart_str_0(&hash_key);
1587-
1588-
if ((field_table = zend_hash_find_ptr(&EG(regular_list), hash_key.s)) != NULL) {
1589-
smart_str_free(&hash_key);
1590-
RETURN_STR_COPY((zend_string *)field_table->ptr);
1591-
} else { /* Not found, lookup by querying PostgreSQL system tables */
1592-
PGresult *tmp_res;
1593-
smart_str querystr = {0};
1594-
zend_resource new_field_table;
1595-
1596-
smart_str_appends(&querystr, "select relname from pg_class where oid=");
1597-
smart_str_append_unsigned(&querystr, oid);
1598-
smart_str_0(&querystr);
1599-
1600-
if ((tmp_res = PQexec(pg_result->conn, ZSTR_VAL(querystr.s))) == NULL || PQresultStatus(tmp_res) != PGRES_TUPLES_OK) {
1601-
if (tmp_res) {
1602-
PQclear(tmp_res);
1603-
}
1604-
smart_str_free(&querystr);
1605-
smart_str_free(&hash_key);
1606-
RETURN_FALSE;
1607-
}
1567+
zend_string *field_table = zend_hash_index_find_ptr(&PGG(table_oids), oid);
1568+
if (field_table) {
1569+
RETURN_STR_COPY(field_table);
1570+
}
16081571

1609-
smart_str_free(&querystr);
1572+
/* Not found, lookup by querying PostgreSQL system tables */
1573+
smart_str querystr = {0};
1574+
smart_str_appends(&querystr, "select relname from pg_class where oid=");
1575+
smart_str_append_unsigned(&querystr, oid);
1576+
smart_str_0(&querystr);
16101577

1611-
if ((table_name = PQgetvalue(tmp_res, 0, 0)) == NULL) {
1578+
PGresult *tmp_res = PQexec(pg_result->conn, ZSTR_VAL(querystr.s));
1579+
smart_str_free(&querystr);
1580+
if (!tmp_res || PQresultStatus(tmp_res) != PGRES_TUPLES_OK) {
1581+
if (tmp_res) {
16121582
PQclear(tmp_res);
1613-
smart_str_free(&hash_key);
1614-
RETURN_FALSE;
16151583
}
1584+
RETURN_FALSE;
1585+
}
16161586

1617-
new_field_table.type = le_string;
1618-
new_field_table.ptr = zend_string_init(table_name, strlen(table_name), 0);
1619-
zend_hash_update_mem(&EG(regular_list), hash_key.s, (void *)&new_field_table, sizeof(zend_resource));
1620-
1621-
smart_str_free(&hash_key);
1587+
char *table_name = PQgetvalue(tmp_res, 0, 0);
1588+
if (!table_name) {
16221589
PQclear(tmp_res);
1623-
RETURN_STR_COPY(new_field_table.ptr);
1590+
RETURN_FALSE;
16241591
}
16251592

1593+
field_table = zend_string_init(table_name, strlen(table_name), 0);
1594+
zend_hash_index_update_ptr(&PGG(table_oids), oid, field_table);
1595+
1596+
PQclear(tmp_res);
1597+
RETURN_STR_COPY(field_table);
16261598
}
16271599
/* }}} */
16281600

@@ -1668,8 +1640,7 @@ static void php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAMETERS, int entry_typ
16681640
RETURN_LONG(PQfsize(pgsql_result, (int)field));
16691641
break;
16701642
case PHP_PG_FIELD_TYPE:
1671-
RETURN_STR(get_field_name(
1672-
pg_result->conn, PQftype(pgsql_result, (int)field), &EG(regular_list)));
1643+
RETURN_STR(get_field_name(pg_result->conn, PQftype(pgsql_result, (int)field)));
16731644
break;
16741645
case PHP_PG_FIELD_TYPE_OID:
16751646

ext/pgsql/php_pgsql.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,8 @@ ZEND_BEGIN_MODULE_GLOBALS(pgsql)
283283
HashTable notices; /* notice message for each connection */
284284
zend_resource *default_link; /* default link when connection is omitted */
285285
HashTable hashes; /* hashes for each connection */
286+
HashTable field_oids;
287+
HashTable table_oids;
286288
ZEND_END_MODULE_GLOBALS(pgsql)
287289

288290
ZEND_EXTERN_MODULE_GLOBALS(pgsql)

0 commit comments

Comments
 (0)