Annotation of embedaddon/php/ext/pgsql/pgsql.c, revision 1.1

1.1     ! misho       1: /*
        !             2:    +----------------------------------------------------------------------+
        !             3:    | PHP Version 5                                                        |
        !             4:    +----------------------------------------------------------------------+
        !             5:    | Copyright (c) 1997-2012 The PHP Group                                |
        !             6:    +----------------------------------------------------------------------+
        !             7:    | This source file is subject to version 3.01 of the PHP license,      |
        !             8:    | that is bundled with this package in the file LICENSE, and is        |
        !             9:    | available through the world-wide-web at the following url:           |
        !            10:    | http://www.php.net/license/3_01.txt                                  |
        !            11:    | If you did not receive a copy of the PHP license and are unable to   |
        !            12:    | obtain it through the world-wide-web, please send a note to          |
        !            13:    | license@php.net so we can mail you a copy immediately.               |
        !            14:    +----------------------------------------------------------------------+
        !            15:    | Authors: Zeev Suraski <zeev@zend.com>                                |
        !            16:    |          Jouni Ahto <jouni.ahto@exdec.fi>                            |
        !            17:    |          Yasuo Ohgaki <yohgaki@php.net>                              |
        !            18:    |          Youichi Iwakiri <yiwakiri@st.rim.or.jp> (pg_copy_*)         | 
        !            19:    |          Chris Kings-Lynne <chriskl@php.net> (v3 protocol)           | 
        !            20:    +----------------------------------------------------------------------+
        !            21:  */
        !            22:  
        !            23: /* $Id: pgsql.c 321634 2012-01-01 13:15:04Z felipe $ */
        !            24: 
        !            25: #include <stdlib.h>
        !            26: 
        !            27: #define PHP_PGSQL_PRIVATE 1
        !            28: 
        !            29: #ifdef HAVE_CONFIG_H
        !            30: #include "config.h"
        !            31: #endif
        !            32: 
        !            33: #define SMART_STR_PREALLOC 512
        !            34: 
        !            35: #include "php.h"
        !            36: #include "php_ini.h"
        !            37: #include "ext/standard/php_standard.h"
        !            38: #include "ext/standard/php_smart_str.h"
        !            39: #include "ext/ereg/php_regex.h"
        !            40: 
        !            41: #undef PACKAGE_BUGREPORT
        !            42: #undef PACKAGE_NAME
        !            43: #undef PACKAGE_STRING
        !            44: #undef PACKAGE_TARNAME
        !            45: #undef PACKAGE_VERSION
        !            46: #include "php_pgsql.h"
        !            47: #include "php_globals.h"
        !            48: #include "zend_exceptions.h"
        !            49: 
        !            50: #if HAVE_PGSQL
        !            51: 
        !            52: #ifndef InvalidOid
        !            53: #define InvalidOid ((Oid) 0)
        !            54: #endif
        !            55: 
        !            56: #define PGSQL_ASSOC            1<<0
        !            57: #define PGSQL_NUM              1<<1
        !            58: #define PGSQL_BOTH             (PGSQL_ASSOC|PGSQL_NUM)
        !            59: 
        !            60: #define PGSQL_STATUS_LONG     1
        !            61: #define PGSQL_STATUS_STRING   2
        !            62: 
        !            63: #define PGSQL_MAX_LENGTH_OF_LONG   30
        !            64: #define PGSQL_MAX_LENGTH_OF_DOUBLE 60
        !            65: 
        !            66: #define PGSQL_RETURN_OID(oid) do { \
        !            67:        if (oid > LONG_MAX) { \
        !            68:                smart_str s = {0}; \
        !            69:                smart_str_append_unsigned(&s, oid); \
        !            70:                smart_str_0(&s); \
        !            71:                RETURN_STRINGL(s.c, s.len, 0); \
        !            72:        } \
        !            73:        RETURN_LONG((long)oid); \
        !            74: } while(0)
        !            75: 
        !            76: 
        !            77: #if HAVE_PQSETNONBLOCKING
        !            78: #define PQ_SETNONBLOCKING(pg_link, flag) PQsetnonblocking(pg_link, flag)
        !            79: #else
        !            80: #define PQ_SETNONBLOCKING(pg_link, flag) 0
        !            81: #endif
        !            82: 
        !            83: #define CHECK_DEFAULT_LINK(x) if ((x) == -1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "No PostgreSQL link opened yet"); }
        !            84: 
        !            85: #ifndef HAVE_PQFREEMEM
        !            86: #define PQfreemem free
        !            87: #endif
        !            88: 
        !            89: ZEND_DECLARE_MODULE_GLOBALS(pgsql)
        !            90: static PHP_GINIT_FUNCTION(pgsql);
        !            91: 
        !            92: /* {{{ arginfo */
        !            93: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_connect, 0, 0, 1)
        !            94:        ZEND_ARG_INFO(0, connection_string)
        !            95:        ZEND_ARG_INFO(0, connect_type)
        !            96:        ZEND_ARG_INFO(0, host)
        !            97:        ZEND_ARG_INFO(0, port)
        !            98:        ZEND_ARG_INFO(0, options)
        !            99:        ZEND_ARG_INFO(0, tty)
        !           100:        ZEND_ARG_INFO(0, database)
        !           101: ZEND_END_ARG_INFO()
        !           102: 
        !           103: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_pconnect, 0, 0, 1)
        !           104:        ZEND_ARG_INFO(0, connection_string)
        !           105:        ZEND_ARG_INFO(0, host)
        !           106:        ZEND_ARG_INFO(0, port)
        !           107:        ZEND_ARG_INFO(0, options)
        !           108:        ZEND_ARG_INFO(0, tty)
        !           109:        ZEND_ARG_INFO(0, database)
        !           110: ZEND_END_ARG_INFO()
        !           111: 
        !           112: #if HAVE_PQPARAMETERSTATUS
        !           113: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_parameter_status, 0, 0, 1)
        !           114:        ZEND_ARG_INFO(0, connection)
        !           115:        ZEND_ARG_INFO(0, param_name)
        !           116: ZEND_END_ARG_INFO()
        !           117: #endif
        !           118: 
        !           119: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_close, 0, 0, 0)
        !           120:        ZEND_ARG_INFO(0, connection)
        !           121: ZEND_END_ARG_INFO()
        !           122: 
        !           123: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_dbname, 0, 0, 0)
        !           124:        ZEND_ARG_INFO(0, connection)
        !           125: ZEND_END_ARG_INFO()
        !           126: 
        !           127: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_last_error, 0, 0, 0)
        !           128:        ZEND_ARG_INFO(0, connection)
        !           129: ZEND_END_ARG_INFO()
        !           130: 
        !           131: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_options, 0, 0, 0)
        !           132:        ZEND_ARG_INFO(0, connection)
        !           133: ZEND_END_ARG_INFO()
        !           134: 
        !           135: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_port, 0, 0, 0)
        !           136:        ZEND_ARG_INFO(0, connection)
        !           137: ZEND_END_ARG_INFO()
        !           138: 
        !           139: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_tty, 0, 0, 0)
        !           140:        ZEND_ARG_INFO(0, connection)
        !           141: ZEND_END_ARG_INFO()
        !           142: 
        !           143: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_host, 0, 0, 0)
        !           144:        ZEND_ARG_INFO(0, connection)
        !           145: ZEND_END_ARG_INFO()
        !           146: 
        !           147: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_version, 0, 0, 0)
        !           148:        ZEND_ARG_INFO(0, connection)
        !           149: ZEND_END_ARG_INFO()
        !           150: 
        !           151: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_ping, 0, 0, 0)
        !           152:        ZEND_ARG_INFO(0, connection)
        !           153: ZEND_END_ARG_INFO()
        !           154: 
        !           155: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_query, 0, 0, 0)
        !           156:        ZEND_ARG_INFO(0, connection)
        !           157:        ZEND_ARG_INFO(0, query)
        !           158: ZEND_END_ARG_INFO()
        !           159: 
        !           160: #if HAVE_PQEXECPARAMS
        !           161: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_query_params, 0, 0, 0)
        !           162:        ZEND_ARG_INFO(0, connection)
        !           163:        ZEND_ARG_INFO(0, query)
        !           164:        ZEND_ARG_INFO(0, params)
        !           165: ZEND_END_ARG_INFO()
        !           166: #endif
        !           167: 
        !           168: #if HAVE_PQPREPARE
        !           169: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_prepare, 0, 0, 0)
        !           170:        ZEND_ARG_INFO(0, connection)
        !           171:        ZEND_ARG_INFO(0, stmtname)
        !           172:        ZEND_ARG_INFO(0, query)
        !           173: ZEND_END_ARG_INFO()
        !           174: #endif
        !           175: 
        !           176: #if HAVE_PQEXECPREPARED
        !           177: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_execute, 0, 0, 0)
        !           178:        ZEND_ARG_INFO(0, connection)
        !           179:        ZEND_ARG_INFO(0, stmtname)
        !           180:        ZEND_ARG_INFO(0, params)
        !           181: ZEND_END_ARG_INFO()
        !           182: #endif
        !           183: 
        !           184: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_num_rows, 0, 0, 1)
        !           185:        ZEND_ARG_INFO(0, result)
        !           186: ZEND_END_ARG_INFO()
        !           187: 
        !           188: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_num_fields, 0, 0, 1)
        !           189:        ZEND_ARG_INFO(0, result)
        !           190: ZEND_END_ARG_INFO()
        !           191: 
        !           192: #if HAVE_PQCMDTUPLES
        !           193: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_affected_rows, 0, 0, 1)
        !           194:        ZEND_ARG_INFO(0, result)
        !           195: ZEND_END_ARG_INFO()
        !           196: #endif
        !           197: 
        !           198: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_last_notice, 0, 0, 1)
        !           199:        ZEND_ARG_INFO(0, connection)
        !           200: ZEND_END_ARG_INFO()
        !           201: 
        !           202: #ifdef HAVE_PQFTABLE
        !           203: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_table, 0, 0, 2)
        !           204:        ZEND_ARG_INFO(0, result)
        !           205:        ZEND_ARG_INFO(0, field_number)
        !           206:        ZEND_ARG_INFO(0, oid_only)
        !           207: ZEND_END_ARG_INFO()
        !           208: #endif
        !           209: 
        !           210: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_name, 0, 0, 2)
        !           211:        ZEND_ARG_INFO(0, result)
        !           212:        ZEND_ARG_INFO(0, field_number)
        !           213: ZEND_END_ARG_INFO()
        !           214: 
        !           215: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_size, 0, 0, 2)
        !           216:        ZEND_ARG_INFO(0, result)
        !           217:        ZEND_ARG_INFO(0, field_number)
        !           218: ZEND_END_ARG_INFO()
        !           219: 
        !           220: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_type, 0, 0, 2)
        !           221:        ZEND_ARG_INFO(0, result)
        !           222:        ZEND_ARG_INFO(0, field_number)
        !           223: ZEND_END_ARG_INFO()
        !           224: 
        !           225: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_type_oid, 0, 0, 2)
        !           226:        ZEND_ARG_INFO(0, result)
        !           227:        ZEND_ARG_INFO(0, field_number)
        !           228: ZEND_END_ARG_INFO()
        !           229: 
        !           230: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_num, 0, 0, 2)
        !           231:        ZEND_ARG_INFO(0, result)
        !           232:        ZEND_ARG_INFO(0, field_name)
        !           233: ZEND_END_ARG_INFO()
        !           234: 
        !           235: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_result, 0, 0, 1)
        !           236:        ZEND_ARG_INFO(0, result)
        !           237:        ZEND_ARG_INFO(0, row_number)
        !           238:        ZEND_ARG_INFO(0, field_name)
        !           239: ZEND_END_ARG_INFO()
        !           240: 
        !           241: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_row, 0, 0, 1)
        !           242:        ZEND_ARG_INFO(0, result)
        !           243:        ZEND_ARG_INFO(0, row)
        !           244:        ZEND_ARG_INFO(0, result_type)
        !           245: ZEND_END_ARG_INFO()
        !           246: 
        !           247: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_assoc, 0, 0, 1)
        !           248:        ZEND_ARG_INFO(0, result)
        !           249:        ZEND_ARG_INFO(0, row)
        !           250: ZEND_END_ARG_INFO()
        !           251: 
        !           252: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_array, 0, 0, 1)
        !           253:        ZEND_ARG_INFO(0, result)
        !           254:        ZEND_ARG_INFO(0, row)
        !           255:        ZEND_ARG_INFO(0, result_type)
        !           256: ZEND_END_ARG_INFO()
        !           257: 
        !           258: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_object, 0, 0, 1)
        !           259:        ZEND_ARG_INFO(0, result)
        !           260:        ZEND_ARG_INFO(0, row)
        !           261:        ZEND_ARG_INFO(0, class_name)
        !           262:        ZEND_ARG_INFO(0, l)
        !           263:        ZEND_ARG_INFO(0, ctor_params)
        !           264: ZEND_END_ARG_INFO()
        !           265: 
        !           266: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_all, 0, 0, 1)
        !           267:        ZEND_ARG_INFO(0, result)
        !           268: ZEND_END_ARG_INFO()
        !           269: 
        !           270: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_all_columns, 0, 0, 1)
        !           271:        ZEND_ARG_INFO(0, result)
        !           272:        ZEND_ARG_INFO(0, column_number)
        !           273: ZEND_END_ARG_INFO()
        !           274: 
        !           275: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_result_seek, 0, 0, 2)
        !           276:        ZEND_ARG_INFO(0, result)
        !           277:        ZEND_ARG_INFO(0, offset)
        !           278: ZEND_END_ARG_INFO()
        !           279: 
        !           280: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_prtlen, 0, 0, 1)
        !           281:        ZEND_ARG_INFO(0, result)
        !           282:        ZEND_ARG_INFO(0, row)
        !           283:        ZEND_ARG_INFO(0, field_name_or_number)
        !           284: ZEND_END_ARG_INFO()
        !           285: 
        !           286: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_is_null, 0, 0, 1)
        !           287:        ZEND_ARG_INFO(0, result)
        !           288:        ZEND_ARG_INFO(0, row)
        !           289:        ZEND_ARG_INFO(0, field_name_or_number)
        !           290: ZEND_END_ARG_INFO()
        !           291: 
        !           292: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_free_result, 0, 0, 1)
        !           293:        ZEND_ARG_INFO(0, result)
        !           294: ZEND_END_ARG_INFO()
        !           295: 
        !           296: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_last_oid, 0, 0, 1)
        !           297:        ZEND_ARG_INFO(0, result)
        !           298: ZEND_END_ARG_INFO()
        !           299: 
        !           300: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_trace, 0, 0, 1)
        !           301:        ZEND_ARG_INFO(0, filename)
        !           302:        ZEND_ARG_INFO(0, mode)
        !           303:        ZEND_ARG_INFO(0, connection)
        !           304: ZEND_END_ARG_INFO()
        !           305: 
        !           306: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_untrace, 0, 0, 0)
        !           307:        ZEND_ARG_INFO(0, connection)
        !           308: ZEND_END_ARG_INFO()
        !           309: 
        !           310: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_create, 0, 0, 0)
        !           311:        ZEND_ARG_INFO(0, connection)
        !           312:        ZEND_ARG_INFO(0, large_object_id)
        !           313: ZEND_END_ARG_INFO()
        !           314: 
        !           315: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_unlink, 0, 0, 0)
        !           316:        ZEND_ARG_INFO(0, connection)
        !           317:        ZEND_ARG_INFO(0, large_object_oid)
        !           318: ZEND_END_ARG_INFO()
        !           319: 
        !           320: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_open, 0, 0, 0)
        !           321:        ZEND_ARG_INFO(0, connection)
        !           322:        ZEND_ARG_INFO(0, large_object_oid)
        !           323:        ZEND_ARG_INFO(0, mode)
        !           324: ZEND_END_ARG_INFO()
        !           325: 
        !           326: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_close, 0, 0, 1)
        !           327:        ZEND_ARG_INFO(0, large_object)
        !           328: ZEND_END_ARG_INFO()
        !           329: 
        !           330: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_read, 0, 0, 1)
        !           331:        ZEND_ARG_INFO(0, large_object)
        !           332:        ZEND_ARG_INFO(0, len)
        !           333: ZEND_END_ARG_INFO()
        !           334: 
        !           335: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_write, 0, 0, 2)
        !           336:        ZEND_ARG_INFO(0, large_object)
        !           337:        ZEND_ARG_INFO(0, buf)
        !           338:        ZEND_ARG_INFO(0, len)
        !           339: ZEND_END_ARG_INFO()
        !           340: 
        !           341: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_read_all, 0, 0, 1)
        !           342:        ZEND_ARG_INFO(0, large_object)
        !           343: ZEND_END_ARG_INFO()
        !           344: 
        !           345: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_import, 0, 0, 0)
        !           346:        ZEND_ARG_INFO(0, connection)
        !           347:        ZEND_ARG_INFO(0, filename)
        !           348:        ZEND_ARG_INFO(0, large_object_oid)
        !           349: ZEND_END_ARG_INFO()
        !           350: 
        !           351: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_export, 0, 0, 0)
        !           352:        ZEND_ARG_INFO(0, connection)
        !           353:        ZEND_ARG_INFO(0, objoid)
        !           354:        ZEND_ARG_INFO(0, filename)
        !           355: ZEND_END_ARG_INFO()
        !           356: 
        !           357: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_seek, 0, 0, 2)
        !           358:        ZEND_ARG_INFO(0, large_object)
        !           359:        ZEND_ARG_INFO(0, offset)
        !           360:        ZEND_ARG_INFO(0, whence)
        !           361: ZEND_END_ARG_INFO()
        !           362: 
        !           363: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_tell, 0, 0, 1)
        !           364:        ZEND_ARG_INFO(0, large_object)
        !           365: ZEND_END_ARG_INFO()
        !           366: 
        !           367: #if HAVE_PQSETERRORVERBOSITY
        !           368: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_set_error_verbosity, 0, 0, 0)
        !           369:        ZEND_ARG_INFO(0, connection)
        !           370:        ZEND_ARG_INFO(0, verbosity)
        !           371: ZEND_END_ARG_INFO()
        !           372: #endif
        !           373: 
        !           374: #if HAVE_PQCLIENTENCODING
        !           375: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_set_client_encoding, 0, 0, 0)
        !           376:        ZEND_ARG_INFO(0, connection)
        !           377:        ZEND_ARG_INFO(0, encoding)
        !           378: ZEND_END_ARG_INFO()
        !           379: 
        !           380: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_client_encoding, 0, 0, 0)
        !           381:        ZEND_ARG_INFO(0, connection)
        !           382: ZEND_END_ARG_INFO()
        !           383: #endif
        !           384: 
        !           385: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_end_copy, 0, 0, 0)
        !           386:        ZEND_ARG_INFO(0, connection)
        !           387: ZEND_END_ARG_INFO()
        !           388: 
        !           389: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_put_line, 0, 0, 0)
        !           390:        ZEND_ARG_INFO(0, connection)
        !           391:        ZEND_ARG_INFO(0, query)
        !           392: ZEND_END_ARG_INFO()
        !           393: 
        !           394: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_copy_to, 0, 0, 2)
        !           395:        ZEND_ARG_INFO(0, connection)
        !           396:        ZEND_ARG_INFO(0, table_name)
        !           397:        ZEND_ARG_INFO(0, delimiter)
        !           398:        ZEND_ARG_INFO(0, null_as)
        !           399: ZEND_END_ARG_INFO()
        !           400: 
        !           401: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_copy_from, 0, 0, 3)
        !           402:        ZEND_ARG_INFO(0, connection)
        !           403:        ZEND_ARG_INFO(0, table_name)
        !           404:        ZEND_ARG_INFO(0, rows)
        !           405:        ZEND_ARG_INFO(0, delimiter)
        !           406:        ZEND_ARG_INFO(0, null_as)
        !           407: ZEND_END_ARG_INFO()
        !           408: 
        !           409: #if HAVE_PQESCAPE
        !           410: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_escape_string, 0, 0, 0)
        !           411:        ZEND_ARG_INFO(0, connection)
        !           412:        ZEND_ARG_INFO(0, data)
        !           413: ZEND_END_ARG_INFO()
        !           414: 
        !           415: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_escape_bytea, 0, 0, 0)
        !           416:        ZEND_ARG_INFO(0, connection)
        !           417:        ZEND_ARG_INFO(0, data)
        !           418: ZEND_END_ARG_INFO()
        !           419: 
        !           420: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_unescape_bytea, 0, 0, 1)
        !           421:        ZEND_ARG_INFO(0, data)
        !           422: ZEND_END_ARG_INFO()
        !           423: #endif
        !           424: 
        !           425: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_result_error, 0, 0, 1)
        !           426:        ZEND_ARG_INFO(0, result)
        !           427: ZEND_END_ARG_INFO()
        !           428: 
        !           429: #if HAVE_PQRESULTERRORFIELD
        !           430: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_result_error_field, 0, 0, 2)
        !           431:        ZEND_ARG_INFO(0, result)
        !           432:        ZEND_ARG_INFO(0, fieldcode)
        !           433: ZEND_END_ARG_INFO()
        !           434: #endif
        !           435: 
        !           436: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_connection_status, 0, 0, 1)
        !           437:        ZEND_ARG_INFO(0, connection)
        !           438: ZEND_END_ARG_INFO()
        !           439: 
        !           440: #if HAVE_PGTRANSACTIONSTATUS
        !           441: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_transaction_status, 0, 0, 1)
        !           442:        ZEND_ARG_INFO(0, connection)
        !           443: ZEND_END_ARG_INFO()
        !           444: #endif
        !           445: 
        !           446: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_connection_reset, 0, 0, 1)
        !           447:        ZEND_ARG_INFO(0, connection)
        !           448: ZEND_END_ARG_INFO()
        !           449: 
        !           450: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_cancel_query, 0, 0, 1)
        !           451:        ZEND_ARG_INFO(0, connection)
        !           452: ZEND_END_ARG_INFO()
        !           453: 
        !           454: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_connection_busy, 0, 0, 1)
        !           455:        ZEND_ARG_INFO(0, connection)
        !           456: ZEND_END_ARG_INFO()
        !           457: 
        !           458: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_send_query, 0, 0, 2)
        !           459:        ZEND_ARG_INFO(0, connection)
        !           460:        ZEND_ARG_INFO(0, query)
        !           461: ZEND_END_ARG_INFO()
        !           462: 
        !           463: #if HAVE_PQSENDQUERYPARAMS
        !           464: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_send_query_params, 0, 0, 3)
        !           465:        ZEND_ARG_INFO(0, connection)
        !           466:        ZEND_ARG_INFO(0, query)
        !           467:        ZEND_ARG_INFO(0, params)
        !           468: ZEND_END_ARG_INFO()
        !           469: #endif
        !           470: 
        !           471: #if HAVE_PQSENDPREPARE
        !           472: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_send_prepare, 0, 0, 3)
        !           473:        ZEND_ARG_INFO(0, connection)
        !           474:        ZEND_ARG_INFO(0, stmtname)
        !           475:        ZEND_ARG_INFO(0, query)
        !           476: ZEND_END_ARG_INFO()
        !           477: #endif
        !           478: 
        !           479: #if HAVE_PQSENDQUERYPREPARED
        !           480: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_send_execute, 0, 0, 3)
        !           481:        ZEND_ARG_INFO(0, connection)
        !           482:        ZEND_ARG_INFO(0, stmtname)
        !           483:        ZEND_ARG_INFO(0, params)
        !           484: ZEND_END_ARG_INFO()
        !           485: #endif
        !           486: 
        !           487: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_get_result, 0, 0, 1)
        !           488:        ZEND_ARG_INFO(0, connection)
        !           489: ZEND_END_ARG_INFO()
        !           490: 
        !           491: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_result_status, 0, 0, 1)
        !           492:        ZEND_ARG_INFO(0, result)
        !           493:        ZEND_ARG_INFO(0, result_type)
        !           494: ZEND_END_ARG_INFO()
        !           495: 
        !           496: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_get_notify, 0, 0, 0)
        !           497:        ZEND_ARG_INFO(0, connection)
        !           498:        ZEND_ARG_INFO(0, e)
        !           499: ZEND_END_ARG_INFO()
        !           500: 
        !           501: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_get_pid, 0, 0, 0)
        !           502:        ZEND_ARG_INFO(0, connection)
        !           503: ZEND_END_ARG_INFO()
        !           504: 
        !           505: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_meta_data, 0, 0, 2)
        !           506:        ZEND_ARG_INFO(0, db)
        !           507:        ZEND_ARG_INFO(0, table)
        !           508: ZEND_END_ARG_INFO()
        !           509: 
        !           510: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_convert, 0, 0, 3)
        !           511:        ZEND_ARG_INFO(0, db)
        !           512:        ZEND_ARG_INFO(0, table)
        !           513:        ZEND_ARG_INFO(0, values)
        !           514:        ZEND_ARG_INFO(0, options)
        !           515: ZEND_END_ARG_INFO()
        !           516: 
        !           517: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_insert, 0, 0, 3)
        !           518:        ZEND_ARG_INFO(0, db)
        !           519:        ZEND_ARG_INFO(0, table)
        !           520:        ZEND_ARG_INFO(0, values)
        !           521:        ZEND_ARG_INFO(0, options)
        !           522: ZEND_END_ARG_INFO()
        !           523: 
        !           524: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_update, 0, 0, 4)
        !           525:        ZEND_ARG_INFO(0, db)
        !           526:        ZEND_ARG_INFO(0, table)
        !           527:        ZEND_ARG_INFO(0, fields)
        !           528:        ZEND_ARG_INFO(0, ids)
        !           529:        ZEND_ARG_INFO(0, options)
        !           530: ZEND_END_ARG_INFO()
        !           531: 
        !           532: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_delete, 0, 0, 3)
        !           533:        ZEND_ARG_INFO(0, db)
        !           534:        ZEND_ARG_INFO(0, table)
        !           535:        ZEND_ARG_INFO(0, ids)
        !           536:        ZEND_ARG_INFO(0, options)
        !           537: ZEND_END_ARG_INFO()
        !           538: 
        !           539: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_select, 0, 0, 3)
        !           540:        ZEND_ARG_INFO(0, db)
        !           541:        ZEND_ARG_INFO(0, table)
        !           542:        ZEND_ARG_INFO(0, ids)
        !           543:        ZEND_ARG_INFO(0, options)
        !           544: ZEND_END_ARG_INFO()
        !           545: /* }}} */
        !           546: 
        !           547: /* {{{ pgsql_functions[]
        !           548:  */
        !           549: const zend_function_entry pgsql_functions[] = {
        !           550:        /* connection functions */
        !           551:        PHP_FE(pg_connect,              arginfo_pg_connect)
        !           552:        PHP_FE(pg_pconnect,             arginfo_pg_pconnect)
        !           553:        PHP_FE(pg_close,                arginfo_pg_close)
        !           554:        PHP_FE(pg_connection_status,    arginfo_pg_connection_status)
        !           555:        PHP_FE(pg_connection_busy,              arginfo_pg_connection_busy)
        !           556:        PHP_FE(pg_connection_reset,             arginfo_pg_connection_reset)
        !           557:        PHP_FE(pg_host,                 arginfo_pg_host)
        !           558:        PHP_FE(pg_dbname,               arginfo_pg_dbname)
        !           559:        PHP_FE(pg_port,                 arginfo_pg_port)
        !           560:        PHP_FE(pg_tty,                  arginfo_pg_tty)
        !           561:        PHP_FE(pg_options,              arginfo_pg_options)
        !           562:        PHP_FE(pg_version,              arginfo_pg_version)
        !           563:        PHP_FE(pg_ping,                 arginfo_pg_ping)
        !           564: #if HAVE_PQPARAMETERSTATUS
        !           565:        PHP_FE(pg_parameter_status, arginfo_pg_parameter_status)
        !           566: #endif
        !           567: #if HAVE_PGTRANSACTIONSTATUS
        !           568:        PHP_FE(pg_transaction_status, arginfo_pg_transaction_status)
        !           569: #endif
        !           570:        /* query functions */
        !           571:        PHP_FE(pg_query,                arginfo_pg_query)
        !           572: #if HAVE_PQEXECPARAMS
        !           573:        PHP_FE(pg_query_params,         arginfo_pg_query_params)
        !           574: #endif
        !           575: #if HAVE_PQPREPARE
        !           576:        PHP_FE(pg_prepare,              arginfo_pg_prepare)
        !           577: #endif
        !           578: #if HAVE_PQEXECPREPARED
        !           579:        PHP_FE(pg_execute,              arginfo_pg_execute)
        !           580: #endif
        !           581:        PHP_FE(pg_send_query,   arginfo_pg_send_query)
        !           582: #if HAVE_PQSENDQUERYPARAMS
        !           583:        PHP_FE(pg_send_query_params,    arginfo_pg_send_query_params)
        !           584: #endif
        !           585: #if HAVE_PQSENDPREPARE
        !           586:        PHP_FE(pg_send_prepare, arginfo_pg_send_prepare)
        !           587: #endif
        !           588: #if HAVE_PQSENDQUERYPREPARED
        !           589:        PHP_FE(pg_send_execute, arginfo_pg_send_execute)
        !           590: #endif
        !           591:        PHP_FE(pg_cancel_query, arginfo_pg_cancel_query)
        !           592:        /* result functions */
        !           593:        PHP_FE(pg_fetch_result, arginfo_pg_fetch_result)
        !           594:        PHP_FE(pg_fetch_row,    arginfo_pg_fetch_row)
        !           595:        PHP_FE(pg_fetch_assoc,  arginfo_pg_fetch_assoc)
        !           596:        PHP_FE(pg_fetch_array,  arginfo_pg_fetch_array)
        !           597:        PHP_FE(pg_fetch_object, arginfo_pg_fetch_object)
        !           598:        PHP_FE(pg_fetch_all,    arginfo_pg_fetch_all)
        !           599:        PHP_FE(pg_fetch_all_columns,    arginfo_pg_fetch_all_columns)
        !           600: #if HAVE_PQCMDTUPLES
        !           601:        PHP_FE(pg_affected_rows,arginfo_pg_affected_rows)
        !           602: #endif
        !           603:        PHP_FE(pg_get_result,   arginfo_pg_get_result)
        !           604:        PHP_FE(pg_result_seek,  arginfo_pg_result_seek)
        !           605:        PHP_FE(pg_result_status,arginfo_pg_result_status)
        !           606:        PHP_FE(pg_free_result,  arginfo_pg_free_result)
        !           607:        PHP_FE(pg_last_oid,         arginfo_pg_last_oid)
        !           608:        PHP_FE(pg_num_rows,             arginfo_pg_num_rows)
        !           609:        PHP_FE(pg_num_fields,   arginfo_pg_num_fields)
        !           610:        PHP_FE(pg_field_name,   arginfo_pg_field_name)
        !           611:        PHP_FE(pg_field_num,    arginfo_pg_field_num)
        !           612:        PHP_FE(pg_field_size,   arginfo_pg_field_size)
        !           613:        PHP_FE(pg_field_type,   arginfo_pg_field_type)
        !           614:        PHP_FE(pg_field_type_oid, arginfo_pg_field_type_oid)
        !           615:        PHP_FE(pg_field_prtlen, arginfo_pg_field_prtlen)
        !           616:        PHP_FE(pg_field_is_null,arginfo_pg_field_is_null)
        !           617: #ifdef HAVE_PQFTABLE
        !           618:        PHP_FE(pg_field_table,  arginfo_pg_field_table)
        !           619: #endif
        !           620:        /* async message function */
        !           621:        PHP_FE(pg_get_notify,   arginfo_pg_get_notify)
        !           622:        PHP_FE(pg_get_pid,      arginfo_pg_get_pid)
        !           623:        /* error message functions */
        !           624:        PHP_FE(pg_result_error, arginfo_pg_result_error)
        !           625: #if HAVE_PQRESULTERRORFIELD
        !           626:        PHP_FE(pg_result_error_field, arginfo_pg_result_error_field)
        !           627: #endif
        !           628:        PHP_FE(pg_last_error,   arginfo_pg_last_error)
        !           629:        PHP_FE(pg_last_notice,  arginfo_pg_last_notice)
        !           630:        /* copy functions */
        !           631:        PHP_FE(pg_put_line,             arginfo_pg_put_line)
        !           632:        PHP_FE(pg_end_copy,             arginfo_pg_end_copy)
        !           633:        PHP_FE(pg_copy_to,      arginfo_pg_copy_to)
        !           634:        PHP_FE(pg_copy_from,    arginfo_pg_copy_from)
        !           635:        /* debug functions */
        !           636:        PHP_FE(pg_trace,                arginfo_pg_trace)
        !           637:        PHP_FE(pg_untrace,              arginfo_pg_untrace)
        !           638:        /* large object functions */
        !           639:        PHP_FE(pg_lo_create,    arginfo_pg_lo_create)
        !           640:        PHP_FE(pg_lo_unlink,    arginfo_pg_lo_unlink)
        !           641:        PHP_FE(pg_lo_open,              arginfo_pg_lo_open)
        !           642:        PHP_FE(pg_lo_close,             arginfo_pg_lo_close)
        !           643:        PHP_FE(pg_lo_read,              arginfo_pg_lo_read)
        !           644:        PHP_FE(pg_lo_write,             arginfo_pg_lo_write)
        !           645:        PHP_FE(pg_lo_read_all,  arginfo_pg_lo_read_all)
        !           646:        PHP_FE(pg_lo_import,    arginfo_pg_lo_import)
        !           647:        PHP_FE(pg_lo_export,    arginfo_pg_lo_export)
        !           648:        PHP_FE(pg_lo_seek,              arginfo_pg_lo_seek)
        !           649:        PHP_FE(pg_lo_tell,              arginfo_pg_lo_tell)
        !           650:        /* utility functions */
        !           651: #if HAVE_PQESCAPE
        !           652:        PHP_FE(pg_escape_string,        arginfo_pg_escape_string)
        !           653:        PHP_FE(pg_escape_bytea,         arginfo_pg_escape_bytea)
        !           654:        PHP_FE(pg_unescape_bytea,       arginfo_pg_unescape_bytea)
        !           655: #endif
        !           656: #if HAVE_PQSETERRORVERBOSITY
        !           657:        PHP_FE(pg_set_error_verbosity,  arginfo_pg_set_error_verbosity)
        !           658: #endif
        !           659: #if HAVE_PQCLIENTENCODING
        !           660:        PHP_FE(pg_client_encoding,              arginfo_pg_client_encoding)
        !           661:        PHP_FE(pg_set_client_encoding,  arginfo_pg_set_client_encoding)
        !           662: #endif
        !           663:        /* misc function */
        !           664:        PHP_FE(pg_meta_data,    arginfo_pg_meta_data)
        !           665:        PHP_FE(pg_convert,      arginfo_pg_convert)
        !           666:        PHP_FE(pg_insert,       arginfo_pg_insert)
        !           667:        PHP_FE(pg_update,       arginfo_pg_update)
        !           668:        PHP_FE(pg_delete,       arginfo_pg_delete)
        !           669:        PHP_FE(pg_select,       arginfo_pg_select)
        !           670:        /* aliases for downwards compatibility */
        !           671:        PHP_FALIAS(pg_exec,          pg_query,          arginfo_pg_query)
        !           672:        PHP_FALIAS(pg_getlastoid,    pg_last_oid,       arginfo_pg_last_oid)
        !           673: #if HAVE_PQCMDTUPLES
        !           674:        PHP_FALIAS(pg_cmdtuples,         pg_affected_rows,  arginfo_pg_affected_rows)
        !           675: #endif
        !           676:        PHP_FALIAS(pg_errormessage,      pg_last_error,     arginfo_pg_last_error)
        !           677:        PHP_FALIAS(pg_numrows,           pg_num_rows,       arginfo_pg_num_rows)
        !           678:        PHP_FALIAS(pg_numfields,         pg_num_fields,     arginfo_pg_num_fields)
        !           679:        PHP_FALIAS(pg_fieldname,         pg_field_name,     arginfo_pg_field_name)
        !           680:        PHP_FALIAS(pg_fieldsize,     pg_field_size,     arginfo_pg_field_size)
        !           681:        PHP_FALIAS(pg_fieldtype,         pg_field_type,     arginfo_pg_field_type)
        !           682:        PHP_FALIAS(pg_fieldnum,      pg_field_num,      arginfo_pg_field_num)
        !           683:        PHP_FALIAS(pg_fieldprtlen,       pg_field_prtlen,   arginfo_pg_field_prtlen)
        !           684:        PHP_FALIAS(pg_fieldisnull,       pg_field_is_null,  arginfo_pg_field_is_null)
        !           685:        PHP_FALIAS(pg_freeresult,    pg_free_result,    arginfo_pg_free_result)
        !           686:        PHP_FALIAS(pg_result,        pg_fetch_result,   arginfo_pg_get_result)
        !           687:        PHP_FALIAS(pg_loreadall,         pg_lo_read_all,    arginfo_pg_lo_read_all)
        !           688:        PHP_FALIAS(pg_locreate,      pg_lo_create,      arginfo_pg_lo_create)
        !           689:        PHP_FALIAS(pg_lounlink,      pg_lo_unlink,      arginfo_pg_lo_unlink)
        !           690:        PHP_FALIAS(pg_loopen,        pg_lo_open,        arginfo_pg_lo_open)
        !           691:        PHP_FALIAS(pg_loclose,       pg_lo_close,       arginfo_pg_lo_close)
        !           692:        PHP_FALIAS(pg_loread,        pg_lo_read,        arginfo_pg_lo_read)
        !           693:        PHP_FALIAS(pg_lowrite,       pg_lo_write,       arginfo_pg_lo_write)
        !           694:        PHP_FALIAS(pg_loimport,      pg_lo_import,      arginfo_pg_lo_import)
        !           695:        PHP_FALIAS(pg_loexport,      pg_lo_export,      arginfo_pg_lo_export)
        !           696: #if HAVE_PQCLIENTENCODING
        !           697:        PHP_FALIAS(pg_clientencoding,           pg_client_encoding,             arginfo_pg_client_encoding)
        !           698:        PHP_FALIAS(pg_setclientencoding,        pg_set_client_encoding, arginfo_pg_set_client_encoding)
        !           699: #endif
        !           700:        PHP_FE_END
        !           701: };
        !           702: /* }}} */
        !           703: 
        !           704: /* {{{ pgsql_module_entry
        !           705:  */
        !           706: zend_module_entry pgsql_module_entry = {
        !           707:        STANDARD_MODULE_HEADER,
        !           708:        "pgsql",
        !           709:        pgsql_functions,
        !           710:        PHP_MINIT(pgsql),
        !           711:        PHP_MSHUTDOWN(pgsql),
        !           712:        PHP_RINIT(pgsql),
        !           713:        PHP_RSHUTDOWN(pgsql),
        !           714:        PHP_MINFO(pgsql),
        !           715:        NO_VERSION_YET,
        !           716:        PHP_MODULE_GLOBALS(pgsql),
        !           717:        PHP_GINIT(pgsql),
        !           718:        NULL,
        !           719:        NULL,
        !           720:        STANDARD_MODULE_PROPERTIES_EX
        !           721: };
        !           722: /* }}} */
        !           723: 
        !           724: #ifdef COMPILE_DL_PGSQL
        !           725: ZEND_GET_MODULE(pgsql)
        !           726: #endif
        !           727: 
        !           728: static int le_link, le_plink, le_result, le_lofp, le_string;
        !           729: 
        !           730: /* {{{ _php_pgsql_trim_message */
        !           731: static char * _php_pgsql_trim_message(const char *message, int *len)
        !           732: {
        !           733:        register int i = strlen(message)-1;
        !           734: 
        !           735:        if (i>1 && (message[i-1] == '\r' || message[i-1] == '\n') && message[i] == '.') {
        !           736:                --i;
        !           737:        }
        !           738:        while (i>0 && (message[i] == '\r' || message[i] == '\n')) {
        !           739:                --i;
        !           740:        }
        !           741:        ++i;
        !           742:        if (len) {
        !           743:                *len = i;
        !           744:        }
        !           745:        return estrndup(message, i);
        !           746: }
        !           747: /* }}} */
        !           748: 
        !           749: /* {{{ _php_pgsql_trim_result */
        !           750: static inline char * _php_pgsql_trim_result(PGconn * pgsql, char **buf)
        !           751: {
        !           752:        return *buf = _php_pgsql_trim_message(PQerrorMessage(pgsql), NULL);
        !           753: }
        !           754: /* }}} */
        !           755: 
        !           756: #define PQErrorMessageTrim(pgsql, buf) _php_pgsql_trim_result(pgsql, buf)
        !           757: 
        !           758: #define PHP_PQ_ERROR(text, pgsql) { \
        !           759:        char *msgbuf = _php_pgsql_trim_message(PQerrorMessage(pgsql), NULL);    \
        !           760:        php_error_docref(NULL TSRMLS_CC, E_WARNING, text, msgbuf);      \
        !           761:        efree(msgbuf);  \
        !           762: } \
        !           763: 
        !           764: /* {{{ php_pgsql_set_default_link
        !           765:  */
        !           766: static void php_pgsql_set_default_link(int id TSRMLS_DC)
        !           767: {   
        !           768:        zend_list_addref(id);
        !           769: 
        !           770:        if (PGG(default_link) != -1) {
        !           771:                zend_list_delete(PGG(default_link));
        !           772:        }
        !           773: 
        !           774:        PGG(default_link) = id;
        !           775: }
        !           776: /* }}} */
        !           777: 
        !           778: /* {{{ _close_pgsql_link
        !           779:  */
        !           780: static void _close_pgsql_link(zend_rsrc_list_entry *rsrc TSRMLS_DC)
        !           781: {
        !           782:        PGconn *link = (PGconn *)rsrc->ptr;
        !           783:        PGresult *res;
        !           784: 
        !           785:        while ((res = PQgetResult(link))) {
        !           786:                PQclear(res);
        !           787:        }
        !           788:        PQfinish(link);
        !           789:        PGG(num_links)--;
        !           790: }
        !           791: /* }}} */
        !           792: 
        !           793: /* {{{ _close_pgsql_plink
        !           794:  */
        !           795: static void _close_pgsql_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC)
        !           796: {
        !           797:        PGconn *link = (PGconn *)rsrc->ptr;
        !           798:        PGresult *res;
        !           799: 
        !           800:        while ((res = PQgetResult(link))) {
        !           801:                PQclear(res);
        !           802:        }
        !           803:        PQfinish(link);
        !           804:        PGG(num_persistent)--;
        !           805:        PGG(num_links)--;
        !           806: }
        !           807: /* }}} */
        !           808: 
        !           809: /* {{{ _php_pgsql_notice_handler
        !           810:  */
        !           811: static void _php_pgsql_notice_handler(void *resource_id, const char *message)
        !           812: {
        !           813:        php_pgsql_notice *notice;
        !           814:        
        !           815:        TSRMLS_FETCH();
        !           816:        if (! PGG(ignore_notices)) {
        !           817:                notice = (php_pgsql_notice *)emalloc(sizeof(php_pgsql_notice));
        !           818:                notice->message = _php_pgsql_trim_message(message, &notice->len);
        !           819:                if (PGG(log_notices)) {
        !           820:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s", notice->message);
        !           821:                }
        !           822:                zend_hash_index_update(&PGG(notices), (ulong)resource_id, (void **)&notice, sizeof(php_pgsql_notice *), NULL);
        !           823:        }
        !           824: }
        !           825: /* }}} */
        !           826: 
        !           827: #define PHP_PGSQL_NOTICE_PTR_DTOR (void (*)(void *))_php_pgsql_notice_ptr_dtor
        !           828: 
        !           829: /* {{{ _php_pgsql_notice_dtor
        !           830:  */
        !           831: static void _php_pgsql_notice_ptr_dtor(void **ptr) 
        !           832: {
        !           833:        php_pgsql_notice *notice = (php_pgsql_notice *)*ptr;
        !           834:        if (notice) {
        !           835:                efree(notice->message);
        !           836:                efree(notice);
        !           837:                notice = NULL;
        !           838:        }
        !           839: }
        !           840: /* }}} */
        !           841: 
        !           842: /* {{{ _rollback_transactions
        !           843:  */
        !           844: static int _rollback_transactions(zend_rsrc_list_entry *rsrc TSRMLS_DC)
        !           845: {
        !           846:        PGconn *link;
        !           847:        PGresult *res;
        !           848:        int orig;
        !           849: 
        !           850:        if (Z_TYPE_P(rsrc) != le_plink) 
        !           851:                return 0;
        !           852: 
        !           853:        link = (PGconn *) rsrc->ptr;
        !           854: 
        !           855:        if (PQ_SETNONBLOCKING(link, 0)) {
        !           856:                php_error_docref("ref.pgsql" TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
        !           857:                return -1;
        !           858:        }
        !           859:        
        !           860:        while ((res = PQgetResult(link))) {
        !           861:                PQclear(res);
        !           862:        }
        !           863: #if HAVE_PGTRANSACTIONSTATUS && HAVE_PQPROTOCOLVERSION
        !           864:        if ((PQprotocolVersion(link) >= 3 && PQtransactionStatus(link) != PQTRANS_IDLE) || PQprotocolVersion(link) < 3)
        !           865: #endif
        !           866:        {
        !           867:                orig = PGG(ignore_notices);
        !           868:                PGG(ignore_notices) = 1;
        !           869: #if HAVE_PGTRANSACTIONSTATUS && HAVE_PQPROTOCOLVERSION
        !           870:                res = PQexec(link,"ROLLBACK;");
        !           871: #else
        !           872:                res = PQexec(link,"BEGIN;");
        !           873:                PQclear(res);
        !           874:                res = PQexec(link,"ROLLBACK;");
        !           875: #endif
        !           876:                PQclear(res);
        !           877:                PGG(ignore_notices) = orig;
        !           878:        }
        !           879: 
        !           880:        return 0;
        !           881: }
        !           882: /* }}} */
        !           883: 
        !           884: /* {{{ _free_ptr
        !           885:  */
        !           886: static void _free_ptr(zend_rsrc_list_entry *rsrc TSRMLS_DC)
        !           887: {
        !           888:        pgLofp *lofp = (pgLofp *)rsrc->ptr;
        !           889:        efree(lofp);
        !           890: }
        !           891: /* }}} */
        !           892: 
        !           893: /* {{{ _free_result
        !           894:  */
        !           895: static void _free_result(zend_rsrc_list_entry *rsrc TSRMLS_DC)
        !           896: {
        !           897:        pgsql_result_handle *pg_result = (pgsql_result_handle *)rsrc->ptr;
        !           898: 
        !           899:        PQclear(pg_result->result);
        !           900:        efree(pg_result);
        !           901: }
        !           902: /* }}} */
        !           903: 
        !           904: /* {{{ PHP_INI
        !           905:  */
        !           906: PHP_INI_BEGIN()
        !           907: STD_PHP_INI_BOOLEAN( "pgsql.allow_persistent",      "1",  PHP_INI_SYSTEM, OnUpdateBool, allow_persistent,      zend_pgsql_globals, pgsql_globals)
        !           908: STD_PHP_INI_ENTRY_EX("pgsql.max_persistent",       "-1",  PHP_INI_SYSTEM, OnUpdateLong, max_persistent,        zend_pgsql_globals, pgsql_globals, display_link_numbers)
        !           909: STD_PHP_INI_ENTRY_EX("pgsql.max_links",            "-1",  PHP_INI_SYSTEM, OnUpdateLong, max_links,             zend_pgsql_globals, pgsql_globals, display_link_numbers)
        !           910: STD_PHP_INI_BOOLEAN( "pgsql.auto_reset_persistent", "0",  PHP_INI_SYSTEM, OnUpdateBool, auto_reset_persistent, zend_pgsql_globals, pgsql_globals)
        !           911: STD_PHP_INI_BOOLEAN( "pgsql.ignore_notice",         "0",  PHP_INI_ALL,    OnUpdateBool, ignore_notices,        zend_pgsql_globals, pgsql_globals)
        !           912: STD_PHP_INI_BOOLEAN( "pgsql.log_notice",            "0",  PHP_INI_ALL,    OnUpdateBool, log_notices,           zend_pgsql_globals, pgsql_globals)
        !           913: PHP_INI_END()
        !           914: /* }}} */
        !           915: 
        !           916: /* {{{ PHP_GINIT_FUNCTION
        !           917:  */
        !           918: static PHP_GINIT_FUNCTION(pgsql)
        !           919: {
        !           920:        memset(pgsql_globals, 0, sizeof(zend_pgsql_globals));
        !           921:        /* Initilize notice message hash at MINIT only */
        !           922:        zend_hash_init_ex(&pgsql_globals->notices, 0, NULL, PHP_PGSQL_NOTICE_PTR_DTOR, 1, 0); 
        !           923: }
        !           924: /* }}} */
        !           925: 
        !           926: /* {{{ PHP_MINIT_FUNCTION
        !           927:  */
        !           928: PHP_MINIT_FUNCTION(pgsql)
        !           929: {
        !           930:        REGISTER_INI_ENTRIES();
        !           931:        
        !           932:        le_link = zend_register_list_destructors_ex(_close_pgsql_link, NULL, "pgsql link", module_number);
        !           933:        le_plink = zend_register_list_destructors_ex(NULL, _close_pgsql_plink, "pgsql link persistent", module_number);
        !           934:        le_result = zend_register_list_destructors_ex(_free_result, NULL, "pgsql result", module_number);
        !           935:        le_lofp = zend_register_list_destructors_ex(_free_ptr, NULL, "pgsql large object", module_number);
        !           936:        le_string = zend_register_list_destructors_ex(_free_ptr, NULL, "pgsql string", module_number);
        !           937:        /* For connection option */
        !           938:        REGISTER_LONG_CONSTANT("PGSQL_CONNECT_FORCE_NEW", PGSQL_CONNECT_FORCE_NEW, CONST_CS | CONST_PERSISTENT);
        !           939:        /* For pg_fetch_array() */
        !           940:        REGISTER_LONG_CONSTANT("PGSQL_ASSOC", PGSQL_ASSOC, CONST_CS | CONST_PERSISTENT);
        !           941:        REGISTER_LONG_CONSTANT("PGSQL_NUM", PGSQL_NUM, CONST_CS | CONST_PERSISTENT);
        !           942:        REGISTER_LONG_CONSTANT("PGSQL_BOTH", PGSQL_BOTH, CONST_CS | CONST_PERSISTENT);
        !           943:        /* For pg_connection_status() */
        !           944:        REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_BAD", CONNECTION_BAD, CONST_CS | CONST_PERSISTENT);
        !           945:        REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_OK", CONNECTION_OK, CONST_CS | CONST_PERSISTENT);
        !           946: #if HAVE_PGTRANSACTIONSTATUS
        !           947:        /* For pg_transaction_status() */
        !           948:        REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_IDLE", PQTRANS_IDLE, CONST_CS | CONST_PERSISTENT);
        !           949:        REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_ACTIVE", PQTRANS_ACTIVE, CONST_CS | CONST_PERSISTENT);
        !           950:        REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_INTRANS", PQTRANS_INTRANS, CONST_CS | CONST_PERSISTENT);
        !           951:        REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_INERROR", PQTRANS_INERROR, CONST_CS | CONST_PERSISTENT);
        !           952:        REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_UNKNOWN", PQTRANS_UNKNOWN, CONST_CS | CONST_PERSISTENT);
        !           953: #endif
        !           954: #if HAVE_PQSETERRORVERBOSITY
        !           955:        /* For pg_set_error_verbosity() */
        !           956:        REGISTER_LONG_CONSTANT("PGSQL_ERRORS_TERSE", PQERRORS_TERSE, CONST_CS | CONST_PERSISTENT);
        !           957:        REGISTER_LONG_CONSTANT("PGSQL_ERRORS_DEFAULT", PQERRORS_DEFAULT, CONST_CS | CONST_PERSISTENT);
        !           958:        REGISTER_LONG_CONSTANT("PGSQL_ERRORS_VERBOSE", PQERRORS_VERBOSE, CONST_CS | CONST_PERSISTENT);
        !           959: #endif
        !           960:        /* For lo_seek() */
        !           961:        REGISTER_LONG_CONSTANT("PGSQL_SEEK_SET", SEEK_SET, CONST_CS | CONST_PERSISTENT);
        !           962:        REGISTER_LONG_CONSTANT("PGSQL_SEEK_CUR", SEEK_CUR, CONST_CS | CONST_PERSISTENT);
        !           963:        REGISTER_LONG_CONSTANT("PGSQL_SEEK_END", SEEK_END, CONST_CS | CONST_PERSISTENT);
        !           964:        /* For pg_result_status() return value type */
        !           965:        REGISTER_LONG_CONSTANT("PGSQL_STATUS_LONG", PGSQL_STATUS_LONG, CONST_CS | CONST_PERSISTENT);
        !           966:        REGISTER_LONG_CONSTANT("PGSQL_STATUS_STRING", PGSQL_STATUS_STRING, CONST_CS | CONST_PERSISTENT);
        !           967:        /* For pg_result_status() return value */
        !           968:        REGISTER_LONG_CONSTANT("PGSQL_EMPTY_QUERY", PGRES_EMPTY_QUERY, CONST_CS | CONST_PERSISTENT);
        !           969:        REGISTER_LONG_CONSTANT("PGSQL_COMMAND_OK", PGRES_COMMAND_OK, CONST_CS | CONST_PERSISTENT);
        !           970:        REGISTER_LONG_CONSTANT("PGSQL_TUPLES_OK", PGRES_TUPLES_OK, CONST_CS | CONST_PERSISTENT);
        !           971:        REGISTER_LONG_CONSTANT("PGSQL_COPY_OUT", PGRES_COPY_OUT, CONST_CS | CONST_PERSISTENT);
        !           972:        REGISTER_LONG_CONSTANT("PGSQL_COPY_IN", PGRES_COPY_IN, CONST_CS | CONST_PERSISTENT);
        !           973:        REGISTER_LONG_CONSTANT("PGSQL_BAD_RESPONSE", PGRES_BAD_RESPONSE, CONST_CS | CONST_PERSISTENT);
        !           974:        REGISTER_LONG_CONSTANT("PGSQL_NONFATAL_ERROR", PGRES_NONFATAL_ERROR, CONST_CS | CONST_PERSISTENT);
        !           975:        REGISTER_LONG_CONSTANT("PGSQL_FATAL_ERROR", PGRES_FATAL_ERROR, CONST_CS | CONST_PERSISTENT);
        !           976: #if HAVE_PQRESULTERRORFIELD
        !           977:        /* For pg_result_error_field() field codes */
        !           978:        REGISTER_LONG_CONSTANT("PGSQL_DIAG_SEVERITY", PG_DIAG_SEVERITY, CONST_CS | CONST_PERSISTENT);
        !           979:        REGISTER_LONG_CONSTANT("PGSQL_DIAG_SQLSTATE", PG_DIAG_SQLSTATE, CONST_CS | CONST_PERSISTENT);
        !           980:        REGISTER_LONG_CONSTANT("PGSQL_DIAG_MESSAGE_PRIMARY", PG_DIAG_MESSAGE_PRIMARY, CONST_CS | CONST_PERSISTENT);
        !           981:        REGISTER_LONG_CONSTANT("PGSQL_DIAG_MESSAGE_DETAIL", PG_DIAG_MESSAGE_DETAIL, CONST_CS | CONST_PERSISTENT);
        !           982:        REGISTER_LONG_CONSTANT("PGSQL_DIAG_MESSAGE_HINT", PG_DIAG_MESSAGE_HINT, CONST_CS | CONST_PERSISTENT);
        !           983:        REGISTER_LONG_CONSTANT("PGSQL_DIAG_STATEMENT_POSITION", PG_DIAG_STATEMENT_POSITION, CONST_CS | CONST_PERSISTENT);
        !           984: #ifdef PG_DIAG_INTERNAL_POSITION
        !           985:        REGISTER_LONG_CONSTANT("PGSQL_DIAG_INTERNAL_POSITION", PG_DIAG_INTERNAL_POSITION, CONST_CS | CONST_PERSISTENT);
        !           986: #endif
        !           987: #ifdef PG_DIAG_INTERNAL_QUERY
        !           988:        REGISTER_LONG_CONSTANT("PGSQL_DIAG_INTERNAL_QUERY", PG_DIAG_INTERNAL_QUERY, CONST_CS | CONST_PERSISTENT);
        !           989: #endif
        !           990:        REGISTER_LONG_CONSTANT("PGSQL_DIAG_CONTEXT", PG_DIAG_CONTEXT, CONST_CS | CONST_PERSISTENT);
        !           991:        REGISTER_LONG_CONSTANT("PGSQL_DIAG_SOURCE_FILE", PG_DIAG_SOURCE_FILE, CONST_CS | CONST_PERSISTENT);
        !           992:        REGISTER_LONG_CONSTANT("PGSQL_DIAG_SOURCE_LINE", PG_DIAG_SOURCE_LINE, CONST_CS | CONST_PERSISTENT);
        !           993:        REGISTER_LONG_CONSTANT("PGSQL_DIAG_SOURCE_FUNCTION", PG_DIAG_SOURCE_FUNCTION, CONST_CS | CONST_PERSISTENT);
        !           994: #endif
        !           995:        /* pg_convert options */
        !           996:        REGISTER_LONG_CONSTANT("PGSQL_CONV_IGNORE_DEFAULT", PGSQL_CONV_IGNORE_DEFAULT, CONST_CS | CONST_PERSISTENT);
        !           997:        REGISTER_LONG_CONSTANT("PGSQL_CONV_FORCE_NULL", PGSQL_CONV_FORCE_NULL, CONST_CS | CONST_PERSISTENT);
        !           998:        REGISTER_LONG_CONSTANT("PGSQL_CONV_IGNORE_NOT_NULL", PGSQL_CONV_IGNORE_NOT_NULL, CONST_CS | CONST_PERSISTENT);
        !           999:        /* pg_insert/update/delete/select options */
        !          1000:        REGISTER_LONG_CONSTANT("PGSQL_DML_NO_CONV", PGSQL_DML_NO_CONV, CONST_CS | CONST_PERSISTENT);
        !          1001:        REGISTER_LONG_CONSTANT("PGSQL_DML_EXEC", PGSQL_DML_EXEC, CONST_CS | CONST_PERSISTENT);
        !          1002:        REGISTER_LONG_CONSTANT("PGSQL_DML_ASYNC", PGSQL_DML_ASYNC, CONST_CS | CONST_PERSISTENT);
        !          1003:        REGISTER_LONG_CONSTANT("PGSQL_DML_STRING", PGSQL_DML_STRING, CONST_CS | CONST_PERSISTENT);
        !          1004:        return SUCCESS;
        !          1005: }
        !          1006: /* }}} */
        !          1007: 
        !          1008: /* {{{ PHP_MSHUTDOWN_FUNCTION
        !          1009:  */
        !          1010: PHP_MSHUTDOWN_FUNCTION(pgsql)
        !          1011: {
        !          1012:        UNREGISTER_INI_ENTRIES();
        !          1013:        zend_hash_destroy(&PGG(notices));
        !          1014: 
        !          1015:        return SUCCESS;
        !          1016: }
        !          1017: /* }}} */
        !          1018: 
        !          1019: /* {{{ PHP_RINIT_FUNCTION
        !          1020:  */
        !          1021: PHP_RINIT_FUNCTION(pgsql)
        !          1022: {
        !          1023:        PGG(default_link)=-1;
        !          1024:        PGG(num_links) = PGG(num_persistent);
        !          1025:        return SUCCESS;
        !          1026: }
        !          1027: /* }}} */
        !          1028: 
        !          1029: /* {{{ PHP_RSHUTDOWN_FUNCTION
        !          1030:  */
        !          1031: PHP_RSHUTDOWN_FUNCTION(pgsql)
        !          1032: {
        !          1033:        /* clean up notice messages */
        !          1034:        zend_hash_clean(&PGG(notices));
        !          1035:        /* clean up persistent connection */
        !          1036:        zend_hash_apply(&EG(persistent_list), (apply_func_t) _rollback_transactions TSRMLS_CC);
        !          1037:        return SUCCESS;
        !          1038: }
        !          1039: /* }}} */
        !          1040: 
        !          1041: /* {{{ PHP_MINFO_FUNCTION
        !          1042:  */
        !          1043: PHP_MINFO_FUNCTION(pgsql)
        !          1044: {
        !          1045:        char buf[256];
        !          1046: 
        !          1047:        php_info_print_table_start();
        !          1048:        php_info_print_table_header(2, "PostgreSQL Support", "enabled");
        !          1049: #if HAVE_PG_CONFIG_H
        !          1050:        php_info_print_table_row(2, "PostgreSQL(libpq) Version", PG_VERSION);
        !          1051: #ifdef HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT
        !          1052:        php_info_print_table_row(2, "Multibyte character support", "enabled");
        !          1053: #else
        !          1054:        php_info_print_table_row(2, "Multibyte character support", "disabled");
        !          1055: #endif
        !          1056: #ifdef USE_SSL
        !          1057:        php_info_print_table_row(2, "SSL support", "enabled");
        !          1058: #else
        !          1059:        php_info_print_table_row(2, "SSL support", "disabled");
        !          1060: #endif
        !          1061: #endif /* HAVE_PG_CONFIG_H */  
        !          1062:        snprintf(buf, sizeof(buf), "%ld", PGG(num_persistent));
        !          1063:        php_info_print_table_row(2, "Active Persistent Links", buf);
        !          1064:        snprintf(buf, sizeof(buf), "%ld", PGG(num_links));
        !          1065:        php_info_print_table_row(2, "Active Links", buf);
        !          1066:        php_info_print_table_end();
        !          1067: 
        !          1068:        DISPLAY_INI_ENTRIES();
        !          1069: }
        !          1070: /* }}} */
        !          1071: 
        !          1072: 
        !          1073: /* {{{ php_pgsql_do_connect
        !          1074:  */
        !          1075: static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
        !          1076: {
        !          1077:        char *host=NULL,*port=NULL,*options=NULL,*tty=NULL,*dbname=NULL,*connstring=NULL;
        !          1078:        PGconn *pgsql;
        !          1079:        smart_str str = {0};
        !          1080:        zval **args[5];
        !          1081:        int i, connect_type = 0;
        !          1082:        PGresult *pg_result;
        !          1083: 
        !          1084:        if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 5
        !          1085:                        || zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
        !          1086:                WRONG_PARAM_COUNT;
        !          1087:        }
        !          1088: 
        !          1089:        smart_str_appends(&str, "pgsql");
        !          1090:        
        !          1091:        for (i = 0; i < ZEND_NUM_ARGS(); i++) {
        !          1092:                /* make sure that the PGSQL_CONNECT_FORCE_NEW bit is not part of the hash so that subsequent connections
        !          1093:                 * can re-use this connection. Bug #39979
        !          1094:                 */ 
        !          1095:                if (i == 1 && ZEND_NUM_ARGS() == 2 && Z_TYPE_PP(args[i]) == IS_LONG) {
        !          1096:                        if (Z_LVAL_PP(args[1]) == PGSQL_CONNECT_FORCE_NEW) {
        !          1097:                                continue;
        !          1098:                        } else if (Z_LVAL_PP(args[1]) & PGSQL_CONNECT_FORCE_NEW) {
        !          1099:                                smart_str_append_long(&str, Z_LVAL_PP(args[1]) ^ PGSQL_CONNECT_FORCE_NEW);
        !          1100:                        }
        !          1101:                }
        !          1102:                convert_to_string_ex(args[i]);
        !          1103:                smart_str_appendc(&str, '_');
        !          1104:                smart_str_appendl(&str, Z_STRVAL_PP(args[i]), Z_STRLEN_PP(args[i]));
        !          1105:        }
        !          1106: 
        !          1107:        smart_str_0(&str);
        !          1108: 
        !          1109:        if (ZEND_NUM_ARGS() == 1) { /* new style, using connection string */
        !          1110:                connstring = Z_STRVAL_PP(args[0]);
        !          1111:        } else if (ZEND_NUM_ARGS() == 2 ) { /* Safe to add conntype_option, since 2 args was illegal */
        !          1112:                connstring = Z_STRVAL_PP(args[0]);
        !          1113:                convert_to_long_ex(args[1]);
        !          1114:                connect_type = Z_LVAL_PP(args[1]);
        !          1115:        } else {
        !          1116:                host = Z_STRVAL_PP(args[0]);
        !          1117:                port = Z_STRVAL_PP(args[1]);
        !          1118:                dbname = Z_STRVAL_PP(args[ZEND_NUM_ARGS()-1]);
        !          1119: 
        !          1120:                switch (ZEND_NUM_ARGS()) {
        !          1121:                case 5:
        !          1122:                        tty = Z_STRVAL_PP(args[3]);
        !          1123:                        /* fall through */
        !          1124:                case 4:
        !          1125:                        options = Z_STRVAL_PP(args[2]);
        !          1126:                        break;
        !          1127:                }
        !          1128:        }
        !          1129:        
        !          1130:        if (persistent && PGG(allow_persistent)) {
        !          1131:                zend_rsrc_list_entry *le;
        !          1132:                
        !          1133:                /* try to find if we already have this link in our persistent list */
        !          1134:                if (zend_hash_find(&EG(persistent_list), str.c, str.len+1, (void **) &le)==FAILURE) {  /* we don't */
        !          1135:                        zend_rsrc_list_entry new_le;
        !          1136:                        
        !          1137:                        if (PGG(max_links)!=-1 && PGG(num_links)>=PGG(max_links)) {
        !          1138:                                php_error_docref(NULL TSRMLS_CC, E_WARNING,
        !          1139:                                                                 "Cannot create new link. Too many open links (%ld)", PGG(num_links));
        !          1140:                                goto err;
        !          1141:                        }
        !          1142:                        if (PGG(max_persistent)!=-1 && PGG(num_persistent)>=PGG(max_persistent)) {
        !          1143:                                php_error_docref(NULL TSRMLS_CC, E_WARNING,
        !          1144:                                                                 "Cannot create new link. Too many open persistent links (%ld)", PGG(num_persistent));
        !          1145:                                goto err;
        !          1146:                        }
        !          1147: 
        !          1148:                        /* create the link */
        !          1149:                        if (connstring) {
        !          1150:                                pgsql=PQconnectdb(connstring);
        !          1151:                        } else {
        !          1152:                                pgsql=PQsetdb(host,port,options,tty,dbname);
        !          1153:                        }
        !          1154:                        if (pgsql==NULL || PQstatus(pgsql)==CONNECTION_BAD) {
        !          1155:                                PHP_PQ_ERROR("Unable to connect to PostgreSQL server: %s", pgsql)
        !          1156:                                if (pgsql) {
        !          1157:                                        PQfinish(pgsql);
        !          1158:                                }
        !          1159:                                goto err;
        !          1160:                        }
        !          1161: 
        !          1162:                        /* hash it up */
        !          1163:                        Z_TYPE(new_le) = le_plink;
        !          1164:                        new_le.ptr = pgsql;
        !          1165:                        if (zend_hash_update(&EG(persistent_list), str.c, str.len+1, (void *) &new_le, sizeof(zend_rsrc_list_entry), NULL)==FAILURE) {
        !          1166:                                goto err;
        !          1167:                        }
        !          1168:                        PGG(num_links)++;
        !          1169:                        PGG(num_persistent)++;
        !          1170:                } else {  /* we do */
        !          1171:                        if (Z_TYPE_P(le) != le_plink) {
        !          1172:                                RETURN_FALSE;
        !          1173:                        }
        !          1174:                        /* ensure that the link did not die */
        !          1175:                        if (PGG(auto_reset_persistent) & 1) {
        !          1176:                                /* need to send & get something from backend to
        !          1177:                                   make sure we catch CONNECTION_BAD everytime */
        !          1178:                                PGresult *pg_result;
        !          1179:                                pg_result = PQexec(le->ptr, "select 1");
        !          1180:                                PQclear(pg_result);
        !          1181:                        }
        !          1182:                        if (PQstatus(le->ptr)==CONNECTION_BAD) { /* the link died */
        !          1183:                                if (le->ptr == NULL) {
        !          1184:                                        if (connstring) {
        !          1185:                                                le->ptr=PQconnectdb(connstring);
        !          1186:                                        } else {
        !          1187:                                                le->ptr=PQsetdb(host,port,options,tty,dbname);
        !          1188:                                        }
        !          1189:                                }
        !          1190:                                else {
        !          1191:                                        PQreset(le->ptr);
        !          1192:                                }
        !          1193:                                if (le->ptr==NULL || PQstatus(le->ptr)==CONNECTION_BAD) {
        !          1194:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING,"PostgreSQL link lost, unable to reconnect");
        !          1195:                                        zend_hash_del(&EG(persistent_list),str.c,str.len+1);
        !          1196:                                        goto err;
        !          1197:                                }
        !          1198:                        }
        !          1199:                        pgsql = (PGconn *) le->ptr;
        !          1200: #if HAVE_PQPROTOCOLVERSION && HAVE_PQPARAMETERSTATUS
        !          1201:                        if (PQprotocolVersion(pgsql) >= 3 && atof(PQparameterStatus(pgsql, "server_version")) >= 7.2) {
        !          1202: #else
        !          1203:                        if (atof(PG_VERSION) >= 7.2) {
        !          1204: #endif
        !          1205:                                pg_result = PQexec(pgsql, "RESET ALL;");
        !          1206:                                PQclear(pg_result);
        !          1207:                        }
        !          1208:                }
        !          1209:                ZEND_REGISTER_RESOURCE(return_value, pgsql, le_plink);
        !          1210:        } else { /* Non persistent connection */
        !          1211:                zend_rsrc_list_entry *index_ptr,new_index_ptr;
        !          1212:                
        !          1213:                /* first we check the hash for the hashed_details key.  if it exists,
        !          1214:                 * it should point us to the right offset where the actual pgsql link sits.
        !          1215:                 * if it doesn't, open a new pgsql link, add it to the resource list,
        !          1216:                 * and add a pointer to it with hashed_details as the key.
        !          1217:                 */
        !          1218:                if (!(connect_type & PGSQL_CONNECT_FORCE_NEW)
        !          1219:                        && zend_hash_find(&EG(regular_list),str.c,str.len+1,(void **) &index_ptr)==SUCCESS) {
        !          1220:                        int type;
        !          1221:                        ulong link;
        !          1222:                        void *ptr;
        !          1223: 
        !          1224:                        if (Z_TYPE_P(index_ptr) != le_index_ptr) {
        !          1225:                                RETURN_FALSE;
        !          1226:                        }
        !          1227:                        link = (ulong) index_ptr->ptr;
        !          1228:                        ptr = zend_list_find(link,&type);   /* check if the link is still there */
        !          1229:                        if (ptr && (type==le_link || type==le_plink)) {
        !          1230:                                Z_LVAL_P(return_value) = link;
        !          1231:                                zend_list_addref(link);
        !          1232:                                php_pgsql_set_default_link(link TSRMLS_CC);
        !          1233:                                Z_TYPE_P(return_value) = IS_RESOURCE;
        !          1234:                                goto cleanup;
        !          1235:                        } else {
        !          1236:                                zend_hash_del(&EG(regular_list),str.c,str.len+1);
        !          1237:                        }
        !          1238:                }
        !          1239:                if (PGG(max_links)!=-1 && PGG(num_links)>=PGG(max_links)) {
        !          1240:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create new link. Too many open links (%ld)", PGG(num_links));
        !          1241:                        goto err;
        !          1242:                }
        !          1243:                if (connstring) {
        !          1244:                        pgsql = PQconnectdb(connstring);
        !          1245:                } else {
        !          1246:                        pgsql = PQsetdb(host,port,options,tty,dbname);
        !          1247:                }
        !          1248:                if (pgsql==NULL || PQstatus(pgsql)==CONNECTION_BAD) {
        !          1249:                        PHP_PQ_ERROR("Unable to connect to PostgreSQL server: %s", pgsql);
        !          1250:                        if (pgsql) {
        !          1251:                                PQfinish(pgsql);
        !          1252:                        }
        !          1253:                        goto err;
        !          1254:                }
        !          1255: 
        !          1256:                /* add it to the list */
        !          1257:                ZEND_REGISTER_RESOURCE(return_value, pgsql, le_link);
        !          1258: 
        !          1259:                /* add it to the hash */
        !          1260:                new_index_ptr.ptr = (void *) Z_LVAL_P(return_value);
        !          1261:                Z_TYPE(new_index_ptr) = le_index_ptr;
        !          1262:                if (zend_hash_update(&EG(regular_list),str.c,str.len+1,(void *) &new_index_ptr, sizeof(zend_rsrc_list_entry), NULL)==FAILURE) {
        !          1263:                        goto err;
        !          1264:                }
        !          1265:                PGG(num_links)++;
        !          1266:        }
        !          1267:        /* set notice processer */
        !          1268:        if (! PGG(ignore_notices) && Z_TYPE_P(return_value) == IS_RESOURCE) {
        !          1269:                PQsetNoticeProcessor(pgsql, _php_pgsql_notice_handler, (void*)Z_RESVAL_P(return_value));
        !          1270:        }
        !          1271:        php_pgsql_set_default_link(Z_LVAL_P(return_value) TSRMLS_CC);
        !          1272:        
        !          1273: cleanup:
        !          1274:        smart_str_free(&str);
        !          1275:        return;
        !          1276:        
        !          1277: err:
        !          1278:        smart_str_free(&str);
        !          1279:        RETURN_FALSE;
        !          1280: }
        !          1281: /* }}} */
        !          1282: 
        !          1283: #if 0
        !          1284: /* {{{ php_pgsql_get_default_link
        !          1285:  */
        !          1286: static int php_pgsql_get_default_link(INTERNAL_FUNCTION_PARAMETERS)
        !          1287: {
        !          1288:        if (PGG(default_link)==-1) { /* no link opened yet, implicitly open one */
        !          1289:                ht = 0;
        !          1290:                php_pgsql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
        !          1291:        }
        !          1292:        return PGG(default_link);
        !          1293: }
        !          1294: /* }}} */
        !          1295: #endif
        !          1296: 
        !          1297: /* {{{ proto resource pg_connect(string connection_string[, int connect_type] | [string host, string port [, string options [, string tty,]]] string database)
        !          1298:    Open a PostgreSQL connection */
        !          1299: PHP_FUNCTION(pg_connect)
        !          1300: {
        !          1301:        php_pgsql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
        !          1302: }
        !          1303: /* }}} */
        !          1304: 
        !          1305: /* {{{ proto resource pg_pconnect(string connection_string | [string host, string port [, string options [, string tty,]]] string database)
        !          1306:    Open a persistent PostgreSQL connection */
        !          1307: PHP_FUNCTION(pg_pconnect)
        !          1308: {
        !          1309:        php_pgsql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,1);
        !          1310: }
        !          1311: /* }}} */
        !          1312: 
        !          1313: /* {{{ proto bool pg_close([resource connection])
        !          1314:    Close a PostgreSQL connection */ 
        !          1315: PHP_FUNCTION(pg_close)
        !          1316: {
        !          1317:        zval *pgsql_link = NULL;
        !          1318:        int id = -1, argc = ZEND_NUM_ARGS();
        !          1319:        PGconn *pgsql;
        !          1320:        
        !          1321:        if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) {
        !          1322:                return;
        !          1323:        }
        !          1324:        
        !          1325:        if (argc == 0) {
        !          1326:                id = PGG(default_link);
        !          1327:                CHECK_DEFAULT_LINK(id);
        !          1328:        }
        !          1329: 
        !          1330:        if (pgsql_link == NULL && id == -1) {
        !          1331:                RETURN_FALSE;
        !          1332:        }       
        !          1333: 
        !          1334:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          1335: 
        !          1336:        if (id==-1) { /* explicit resource number */
        !          1337:                zend_list_delete(Z_RESVAL_P(pgsql_link));
        !          1338:        }
        !          1339: 
        !          1340:        if (id!=-1 
        !          1341:                || (pgsql_link && Z_RESVAL_P(pgsql_link)==PGG(default_link))) {
        !          1342:                zend_list_delete(PGG(default_link));
        !          1343:                PGG(default_link) = -1;
        !          1344:        }
        !          1345: 
        !          1346:        RETURN_TRUE;
        !          1347: }
        !          1348: /* }}} */
        !          1349: 
        !          1350: 
        !          1351: #define PHP_PG_DBNAME 1
        !          1352: #define PHP_PG_ERROR_MESSAGE 2
        !          1353: #define PHP_PG_OPTIONS 3
        !          1354: #define PHP_PG_PORT 4
        !          1355: #define PHP_PG_TTY 5
        !          1356: #define PHP_PG_HOST 6
        !          1357: #define PHP_PG_VERSION 7
        !          1358: 
        !          1359: /* {{{ php_pgsql_get_link_info
        !          1360:  */
        !          1361: static void php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
        !          1362: {
        !          1363:        zval *pgsql_link = NULL;
        !          1364:        int id = -1, argc = ZEND_NUM_ARGS();
        !          1365:        PGconn *pgsql;
        !          1366:        char *msgbuf;
        !          1367: 
        !          1368:        if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) {
        !          1369:                return;
        !          1370:        }
        !          1371:        
        !          1372:        if (argc == 0) {
        !          1373:                id = PGG(default_link);
        !          1374:                CHECK_DEFAULT_LINK(id);
        !          1375:        }
        !          1376:        
        !          1377:        if (pgsql_link == NULL && id == -1) {
        !          1378:                RETURN_FALSE;
        !          1379:        }       
        !          1380: 
        !          1381:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          1382: 
        !          1383:        switch(entry_type) {
        !          1384:                case PHP_PG_DBNAME:
        !          1385:                        Z_STRVAL_P(return_value) = PQdb(pgsql);
        !          1386:                        break;
        !          1387:                case PHP_PG_ERROR_MESSAGE:
        !          1388:                        RETURN_STRING(PQErrorMessageTrim(pgsql, &msgbuf), 0);
        !          1389:                        return;
        !          1390:                case PHP_PG_OPTIONS:
        !          1391:                        Z_STRVAL_P(return_value) = PQoptions(pgsql);
        !          1392:                        break;
        !          1393:                case PHP_PG_PORT:
        !          1394:                        Z_STRVAL_P(return_value) = PQport(pgsql);
        !          1395:                        break;
        !          1396:                case PHP_PG_TTY:
        !          1397:                        Z_STRVAL_P(return_value) = PQtty(pgsql);
        !          1398:                        break;
        !          1399:                case PHP_PG_HOST:
        !          1400:                        Z_STRVAL_P(return_value) = PQhost(pgsql);
        !          1401:                        break;
        !          1402:                case PHP_PG_VERSION:
        !          1403:                        array_init(return_value);
        !          1404:                        add_assoc_string(return_value, "client", PG_VERSION, 1);
        !          1405: #if HAVE_PQPROTOCOLVERSION
        !          1406:                        add_assoc_long(return_value, "protocol", PQprotocolVersion(pgsql));
        !          1407: #if HAVE_PQPARAMETERSTATUS
        !          1408:                        if (PQprotocolVersion(pgsql) >= 3) {
        !          1409:                                add_assoc_string(return_value, "server", (char*)PQparameterStatus(pgsql, "server_version"), 1);
        !          1410:                        }
        !          1411: #endif
        !          1412: #endif
        !          1413:                        return;
        !          1414:                default:
        !          1415:                        RETURN_FALSE;
        !          1416:        }
        !          1417:        if (Z_STRVAL_P(return_value)) {
        !          1418:                Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
        !          1419:                Z_STRVAL_P(return_value) = (char *) estrdup(Z_STRVAL_P(return_value));
        !          1420:        } else {
        !          1421:                Z_STRLEN_P(return_value) = 0;
        !          1422:                Z_STRVAL_P(return_value) = (char *) estrdup("");
        !          1423:        }
        !          1424:        Z_TYPE_P(return_value) = IS_STRING;
        !          1425: }
        !          1426: /* }}} */
        !          1427: 
        !          1428: /* {{{ proto string pg_dbname([resource connection])
        !          1429:    Get the database name */ 
        !          1430: PHP_FUNCTION(pg_dbname)
        !          1431: {
        !          1432:        php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_DBNAME);
        !          1433: }
        !          1434: /* }}} */
        !          1435: 
        !          1436: /* {{{ proto string pg_last_error([resource connection])
        !          1437:    Get the error message string */
        !          1438: PHP_FUNCTION(pg_last_error)
        !          1439: {
        !          1440:        php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_ERROR_MESSAGE);
        !          1441: }
        !          1442: /* }}} */
        !          1443: 
        !          1444: /* {{{ proto string pg_options([resource connection])
        !          1445:    Get the options associated with the connection */
        !          1446: PHP_FUNCTION(pg_options)
        !          1447: {
        !          1448:        php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_OPTIONS);
        !          1449: }
        !          1450: /* }}} */
        !          1451: 
        !          1452: /* {{{ proto int pg_port([resource connection])
        !          1453:    Return the port number associated with the connection */
        !          1454: PHP_FUNCTION(pg_port)
        !          1455: {
        !          1456:        php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_PORT);
        !          1457: }
        !          1458: /* }}} */
        !          1459: 
        !          1460: /* {{{ proto string pg_tty([resource connection])
        !          1461:    Return the tty name associated with the connection */
        !          1462: PHP_FUNCTION(pg_tty)
        !          1463: {
        !          1464:        php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_TTY);
        !          1465: }
        !          1466: /* }}} */
        !          1467: 
        !          1468: /* {{{ proto string pg_host([resource connection])
        !          1469:    Returns the host name associated with the connection */
        !          1470: PHP_FUNCTION(pg_host)
        !          1471: {
        !          1472:        php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_HOST);
        !          1473: }
        !          1474: /* }}} */
        !          1475: 
        !          1476: /* {{{ proto array pg_version([resource connection])
        !          1477:    Returns an array with client, protocol and server version (when available) */
        !          1478: PHP_FUNCTION(pg_version)
        !          1479: {
        !          1480:        php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_VERSION);
        !          1481: }
        !          1482: /* }}} */
        !          1483: 
        !          1484: #if HAVE_PQPARAMETERSTATUS
        !          1485: /* {{{ proto string|false pg_parameter_status([resource connection,] string param_name)
        !          1486:    Returns the value of a server parameter */
        !          1487: PHP_FUNCTION(pg_parameter_status)
        !          1488: {
        !          1489:        zval *pgsql_link;
        !          1490:        int id;
        !          1491:        PGconn *pgsql;
        !          1492:        char *param;
        !          1493:        int len;
        !          1494: 
        !          1495:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pgsql_link, &param, &len) == SUCCESS) {
        !          1496:                id = -1;
        !          1497:        } else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &param, &len) == SUCCESS) {
        !          1498:                pgsql_link = NULL;
        !          1499:                id = PGG(default_link);
        !          1500:        } else {
        !          1501:                RETURN_FALSE;
        !          1502:        }
        !          1503:        if (pgsql_link == NULL && id == -1) {
        !          1504:                RETURN_FALSE;
        !          1505:        }       
        !          1506: 
        !          1507:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          1508: 
        !          1509:        param = (char*)PQparameterStatus(pgsql, param);
        !          1510:        if (param) {
        !          1511:                RETURN_STRING(param, 1);
        !          1512:        } else {
        !          1513:                RETURN_FALSE;
        !          1514:        }
        !          1515: }
        !          1516: /* }}} */
        !          1517: #endif
        !          1518: 
        !          1519: /* {{{ proto bool pg_ping([resource connection])
        !          1520:    Ping database. If connection is bad, try to reconnect. */
        !          1521: PHP_FUNCTION(pg_ping)
        !          1522: {
        !          1523:        zval *pgsql_link;
        !          1524:        int id;
        !          1525:        PGconn *pgsql;
        !          1526:        PGresult *res;
        !          1527: 
        !          1528:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r", &pgsql_link) == SUCCESS) {
        !          1529:                id = -1;
        !          1530:        } else {
        !          1531:                pgsql_link = NULL;
        !          1532:                id = PGG(default_link);
        !          1533:        }
        !          1534:        if (pgsql_link == NULL && id == -1) {
        !          1535:                RETURN_FALSE;
        !          1536:        }       
        !          1537: 
        !          1538:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          1539: 
        !          1540:        /* ping connection */
        !          1541:        res = PQexec(pgsql, "SELECT 1;");
        !          1542:        PQclear(res);
        !          1543: 
        !          1544:        /* check status. */
        !          1545:        if (PQstatus(pgsql) == CONNECTION_OK)
        !          1546:                RETURN_TRUE;
        !          1547: 
        !          1548:        /* reset connection if it's broken */
        !          1549:        PQreset(pgsql);
        !          1550:        if (PQstatus(pgsql) == CONNECTION_OK) {
        !          1551:                RETURN_TRUE;
        !          1552:        }
        !          1553:        RETURN_FALSE;
        !          1554: }
        !          1555: /* }}} */
        !          1556: 
        !          1557: /* {{{ proto resource pg_query([resource connection,] string query)
        !          1558:    Execute a query */
        !          1559: PHP_FUNCTION(pg_query)
        !          1560: {
        !          1561:        zval *pgsql_link = NULL;
        !          1562:        char *query;
        !          1563:        int id = -1, query_len, argc = ZEND_NUM_ARGS();
        !          1564:        int leftover = 0;
        !          1565:        PGconn *pgsql;
        !          1566:        PGresult *pgsql_result;
        !          1567:        ExecStatusType status;
        !          1568:        pgsql_result_handle *pg_result;
        !          1569: 
        !          1570:        if (argc == 1) {
        !          1571:                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &query, &query_len) == FAILURE) {
        !          1572:                        return;
        !          1573:                }
        !          1574:                id = PGG(default_link);
        !          1575:                CHECK_DEFAULT_LINK(id);
        !          1576:        } else {
        !          1577:                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pgsql_link, &query, &query_len) == FAILURE) {
        !          1578:                        return;
        !          1579:                }
        !          1580:        }
        !          1581: 
        !          1582:        if (pgsql_link == NULL && id == -1) {
        !          1583:                RETURN_FALSE;
        !          1584:        }
        !          1585: 
        !          1586:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          1587: 
        !          1588:        if (PQ_SETNONBLOCKING(pgsql, 0)) {
        !          1589:                php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to blocking mode");
        !          1590:                RETURN_FALSE;
        !          1591:        }
        !          1592:        while ((pgsql_result = PQgetResult(pgsql))) {
        !          1593:                PQclear(pgsql_result);
        !          1594:                leftover = 1;
        !          1595:        }
        !          1596:        if (leftover) {
        !          1597:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first");
        !          1598:        }
        !          1599:        pgsql_result = PQexec(pgsql, query);
        !          1600:        if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
        !          1601:                PQclear(pgsql_result);
        !          1602:                PQreset(pgsql);
        !          1603:                pgsql_result = PQexec(pgsql, query);
        !          1604:        }
        !          1605: 
        !          1606:        if (pgsql_result) {
        !          1607:                status = PQresultStatus(pgsql_result);
        !          1608:        } else {
        !          1609:                status = (ExecStatusType) PQstatus(pgsql);
        !          1610:        }
        !          1611:        
        !          1612:        switch (status) {
        !          1613:                case PGRES_EMPTY_QUERY:
        !          1614:                case PGRES_BAD_RESPONSE:
        !          1615:                case PGRES_NONFATAL_ERROR:
        !          1616:                case PGRES_FATAL_ERROR:
        !          1617:                        PHP_PQ_ERROR("Query failed: %s", pgsql);
        !          1618:                        PQclear(pgsql_result);
        !          1619:                        RETURN_FALSE;
        !          1620:                        break;
        !          1621:                case PGRES_COMMAND_OK: /* successful command that did not return rows */
        !          1622:                default:
        !          1623:                        if (pgsql_result) {
        !          1624:                                pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle));
        !          1625:                                pg_result->conn = pgsql;
        !          1626:                                pg_result->result = pgsql_result;
        !          1627:                                pg_result->row = 0;
        !          1628:                                ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result);
        !          1629:                        } else {
        !          1630:                                PQclear(pgsql_result);
        !          1631:                                RETURN_FALSE;
        !          1632:                        }
        !          1633:                        break;
        !          1634:        }
        !          1635: }
        !          1636: /* }}} */
        !          1637: 
        !          1638: #if HAVE_PQEXECPARAMS || HAVE_PQEXECPREPARED || HAVE_PQSENDQUERYPARAMS || HAVE_PQSENDQUERYPREPARED
        !          1639: /* {{{ _php_pgsql_free_params */
        !          1640: static void _php_pgsql_free_params(char **params, int num_params)
        !          1641: {
        !          1642:        if (num_params > 0) {
        !          1643:                int i;
        !          1644:                for (i = 0; i < num_params; i++) {
        !          1645:                        if (params[i]) {
        !          1646:                                efree(params[i]);
        !          1647:                        }
        !          1648:                }
        !          1649:                efree(params);
        !          1650:        }
        !          1651: }
        !          1652: /* }}} */
        !          1653: #endif
        !          1654: 
        !          1655: #if HAVE_PQEXECPARAMS
        !          1656: /* {{{ proto resource pg_query_params([resource connection,] string query, array params)
        !          1657:    Execute a query */
        !          1658: PHP_FUNCTION(pg_query_params)
        !          1659: {
        !          1660:        zval *pgsql_link = NULL;
        !          1661:        zval *pv_param_arr, **tmp;
        !          1662:        char *query;
        !          1663:        int query_len, id = -1, argc = ZEND_NUM_ARGS();
        !          1664:        int leftover = 0;
        !          1665:        int num_params = 0;
        !          1666:        char **params = NULL;
        !          1667:        PGconn *pgsql;
        !          1668:        PGresult *pgsql_result;
        !          1669:        ExecStatusType status;
        !          1670:        pgsql_result_handle *pg_result;
        !          1671:        
        !          1672:        if (argc == 2) {
        !          1673:                if (zend_parse_parameters(argc TSRMLS_CC, "sa", &query, &query_len, &pv_param_arr) == FAILURE) {
        !          1674:                        return;
        !          1675:                }
        !          1676:                id = PGG(default_link);
        !          1677:                CHECK_DEFAULT_LINK(id);
        !          1678:        } else {
        !          1679:                if (zend_parse_parameters(argc TSRMLS_CC, "rsa", &pgsql_link, &query, &query_len, &pv_param_arr) == FAILURE) {
        !          1680:                        return;
        !          1681:                }
        !          1682:        }
        !          1683: 
        !          1684:        if (pgsql_link == NULL && id == -1) {
        !          1685:                RETURN_FALSE;
        !          1686:        }
        !          1687: 
        !          1688:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          1689: 
        !          1690:        if (PQ_SETNONBLOCKING(pgsql, 0)) {
        !          1691:                php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to blocking mode");
        !          1692:                RETURN_FALSE;
        !          1693:        }
        !          1694:        while ((pgsql_result = PQgetResult(pgsql))) {
        !          1695:                PQclear(pgsql_result);
        !          1696:                leftover = 1;
        !          1697:        }
        !          1698:        if (leftover) {
        !          1699:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first");
        !          1700:        }
        !          1701: 
        !          1702:        zend_hash_internal_pointer_reset(Z_ARRVAL_P(pv_param_arr));
        !          1703:        num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr));
        !          1704:        if (num_params > 0) {
        !          1705:                int i = 0;
        !          1706:                params = (char **)safe_emalloc(sizeof(char *), num_params, 0);
        !          1707:                
        !          1708:                for(i = 0; i < num_params; i++) {
        !          1709:                        if (zend_hash_get_current_data(Z_ARRVAL_P(pv_param_arr), (void **) &tmp) == FAILURE) {
        !          1710:                                php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error getting parameter");
        !          1711:                                _php_pgsql_free_params(params, num_params);
        !          1712:                                RETURN_FALSE;
        !          1713:                        }
        !          1714: 
        !          1715:                        if (Z_TYPE_PP(tmp) == IS_NULL) {
        !          1716:                                params[i] = NULL;
        !          1717:                        } else {
        !          1718:                                zval tmp_val = **tmp;
        !          1719:                                zval_copy_ctor(&tmp_val);
        !          1720:                                convert_to_string(&tmp_val);
        !          1721:                                if (Z_TYPE(tmp_val) != IS_STRING) {
        !          1722:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error converting parameter");
        !          1723:                                        zval_dtor(&tmp_val);
        !          1724:                                        _php_pgsql_free_params(params, num_params);
        !          1725:                                        RETURN_FALSE;
        !          1726:                                }
        !          1727:                                params[i] = estrndup(Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
        !          1728:                                zval_dtor(&tmp_val);
        !          1729:                        }
        !          1730: 
        !          1731:                        zend_hash_move_forward(Z_ARRVAL_P(pv_param_arr));
        !          1732:                }
        !          1733:        }
        !          1734: 
        !          1735:        pgsql_result = PQexecParams(pgsql, query, num_params, 
        !          1736:                                        NULL, (const char * const *)params, NULL, NULL, 0);
        !          1737:        if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
        !          1738:                PQclear(pgsql_result);
        !          1739:                PQreset(pgsql);
        !          1740:                pgsql_result = PQexecParams(pgsql, query, num_params, 
        !          1741:                                                NULL, (const char * const *)params, NULL, NULL, 0);
        !          1742:        }
        !          1743: 
        !          1744:        if (pgsql_result) {
        !          1745:                status = PQresultStatus(pgsql_result);
        !          1746:        } else {
        !          1747:                status = (ExecStatusType) PQstatus(pgsql);
        !          1748:        }
        !          1749:        
        !          1750:        _php_pgsql_free_params(params, num_params);
        !          1751: 
        !          1752:        switch (status) {
        !          1753:                case PGRES_EMPTY_QUERY:
        !          1754:                case PGRES_BAD_RESPONSE:
        !          1755:                case PGRES_NONFATAL_ERROR:
        !          1756:                case PGRES_FATAL_ERROR:
        !          1757:                        PHP_PQ_ERROR("Query failed: %s", pgsql);
        !          1758:                        PQclear(pgsql_result);
        !          1759:                        RETURN_FALSE;
        !          1760:                        break;
        !          1761:                case PGRES_COMMAND_OK: /* successful command that did not return rows */
        !          1762:                default:
        !          1763:                        if (pgsql_result) {
        !          1764:                                pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle));
        !          1765:                                pg_result->conn = pgsql;
        !          1766:                                pg_result->result = pgsql_result;
        !          1767:                                pg_result->row = 0;
        !          1768:                                ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result);
        !          1769:                        } else {
        !          1770:                                PQclear(pgsql_result);
        !          1771:                                RETURN_FALSE;
        !          1772:                        }
        !          1773:                        break;
        !          1774:        }
        !          1775: }
        !          1776: /* }}} */
        !          1777: #endif
        !          1778: 
        !          1779: #if HAVE_PQPREPARE
        !          1780: /* {{{ proto resource pg_prepare([resource connection,] string stmtname, string query)
        !          1781:    Prepare a query for future execution */
        !          1782: PHP_FUNCTION(pg_prepare)
        !          1783: {
        !          1784:        zval *pgsql_link = NULL;
        !          1785:        char *query, *stmtname;
        !          1786:        int query_len, stmtname_len, id = -1, argc = ZEND_NUM_ARGS();
        !          1787:        int leftover = 0;
        !          1788:        PGconn *pgsql;
        !          1789:        PGresult *pgsql_result;
        !          1790:        ExecStatusType status;
        !          1791:        pgsql_result_handle *pg_result;
        !          1792: 
        !          1793:        if (argc == 2) {
        !          1794:                if (zend_parse_parameters(argc TSRMLS_CC, "ss", &stmtname, &stmtname_len, &query, &query_len) == FAILURE) {
        !          1795:                        return;
        !          1796:                }
        !          1797:                id = PGG(default_link);
        !          1798:                CHECK_DEFAULT_LINK(id);
        !          1799:        } else {
        !          1800:                if (zend_parse_parameters(argc TSRMLS_CC, "rss", &pgsql_link, &stmtname, &stmtname_len, &query, &query_len) == FAILURE) {
        !          1801:                        return;
        !          1802:                }
        !          1803:        }
        !          1804:        
        !          1805:        if (pgsql_link == NULL && id == -1) {
        !          1806:                RETURN_FALSE;
        !          1807:        }       
        !          1808: 
        !          1809:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          1810: 
        !          1811:        if (PQ_SETNONBLOCKING(pgsql, 0)) {
        !          1812:                php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to blocking mode");
        !          1813:                RETURN_FALSE;
        !          1814:        }
        !          1815:        while ((pgsql_result = PQgetResult(pgsql))) {
        !          1816:                PQclear(pgsql_result);
        !          1817:                leftover = 1;
        !          1818:        }
        !          1819:        if (leftover) {
        !          1820:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first");
        !          1821:        }
        !          1822:        pgsql_result = PQprepare(pgsql, stmtname, query, 0, NULL);
        !          1823:        if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
        !          1824:                PQclear(pgsql_result);
        !          1825:                PQreset(pgsql);
        !          1826:                pgsql_result = PQprepare(pgsql, stmtname, query, 0, NULL);
        !          1827:        }
        !          1828: 
        !          1829:        if (pgsql_result) {
        !          1830:                status = PQresultStatus(pgsql_result);
        !          1831:        } else {
        !          1832:                status = (ExecStatusType) PQstatus(pgsql);
        !          1833:        }
        !          1834:        
        !          1835:        switch (status) {
        !          1836:                case PGRES_EMPTY_QUERY:
        !          1837:                case PGRES_BAD_RESPONSE:
        !          1838:                case PGRES_NONFATAL_ERROR:
        !          1839:                case PGRES_FATAL_ERROR:
        !          1840:                        PHP_PQ_ERROR("Query failed: %s", pgsql);
        !          1841:                        PQclear(pgsql_result);
        !          1842:                        RETURN_FALSE;
        !          1843:                        break;
        !          1844:                case PGRES_COMMAND_OK: /* successful command that did not return rows */
        !          1845:                default:
        !          1846:                        if (pgsql_result) {
        !          1847:                                pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle));
        !          1848:                                pg_result->conn = pgsql;
        !          1849:                                pg_result->result = pgsql_result;
        !          1850:                                pg_result->row = 0;
        !          1851:                                ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result);
        !          1852:                        } else {
        !          1853:                                PQclear(pgsql_result);
        !          1854:                                RETURN_FALSE;
        !          1855:                        }
        !          1856:                        break;
        !          1857:        }
        !          1858: }
        !          1859: /* }}} */
        !          1860: #endif
        !          1861: 
        !          1862: #if HAVE_PQEXECPREPARED
        !          1863: /* {{{ proto resource pg_execute([resource connection,] string stmtname, array params)
        !          1864:    Execute a prepared query  */
        !          1865: PHP_FUNCTION(pg_execute)
        !          1866: {
        !          1867:        zval *pgsql_link = NULL;
        !          1868:        zval *pv_param_arr, **tmp;
        !          1869:        char *stmtname;
        !          1870:        int stmtname_len, id = -1, argc = ZEND_NUM_ARGS();
        !          1871:        int leftover = 0;
        !          1872:        int num_params = 0;
        !          1873:        char **params = NULL;
        !          1874:        PGconn *pgsql;
        !          1875:        PGresult *pgsql_result;
        !          1876:        ExecStatusType status;
        !          1877:        pgsql_result_handle *pg_result;
        !          1878: 
        !          1879:        if (argc == 2) {
        !          1880:                if (zend_parse_parameters(argc TSRMLS_CC, "sa/", &stmtname, &stmtname_len, &pv_param_arr)==FAILURE) {
        !          1881:                        return;
        !          1882:                }
        !          1883:                id = PGG(default_link);
        !          1884:                CHECK_DEFAULT_LINK(id);
        !          1885:        } else {
        !          1886:                if (zend_parse_parameters(argc TSRMLS_CC, "rsa/", &pgsql_link, &stmtname, &stmtname_len, &pv_param_arr) == FAILURE) {
        !          1887:                        return;
        !          1888:                }
        !          1889:        }
        !          1890: 
        !          1891:        if (pgsql_link == NULL && id == -1) {
        !          1892:                RETURN_FALSE;
        !          1893:        }
        !          1894: 
        !          1895:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          1896: 
        !          1897:        if (PQ_SETNONBLOCKING(pgsql, 0)) {
        !          1898:                php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to blocking mode");
        !          1899:                RETURN_FALSE;
        !          1900:        }
        !          1901:        while ((pgsql_result = PQgetResult(pgsql))) {
        !          1902:                PQclear(pgsql_result);
        !          1903:                leftover = 1;
        !          1904:        }
        !          1905:        if (leftover) {
        !          1906:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first");
        !          1907:        }
        !          1908: 
        !          1909:        zend_hash_internal_pointer_reset(Z_ARRVAL_P(pv_param_arr));
        !          1910:        num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr));
        !          1911:        if (num_params > 0) {
        !          1912:                int i = 0;
        !          1913:                params = (char **)safe_emalloc(sizeof(char *), num_params, 0);
        !          1914:                
        !          1915:                for(i = 0; i < num_params; i++) {
        !          1916:                        if (zend_hash_get_current_data(Z_ARRVAL_P(pv_param_arr), (void **) &tmp) == FAILURE) {
        !          1917:                                php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error getting parameter");
        !          1918:                                _php_pgsql_free_params(params, num_params);
        !          1919:                                RETURN_FALSE;
        !          1920:                        }
        !          1921: 
        !          1922:                        if (Z_TYPE_PP(tmp) == IS_NULL) {
        !          1923:                                params[i] = NULL;
        !          1924:                        } else {
        !          1925:                                zval tmp_val = **tmp;
        !          1926:                                zval_copy_ctor(&tmp_val);
        !          1927:                                convert_to_string(&tmp_val);
        !          1928:                                if (Z_TYPE(tmp_val) != IS_STRING) {
        !          1929:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error converting parameter");
        !          1930:                                        zval_dtor(&tmp_val);
        !          1931:                                        _php_pgsql_free_params(params, num_params);
        !          1932:                                        RETURN_FALSE;
        !          1933:                                }
        !          1934:                                params[i] = estrndup(Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
        !          1935:                                zval_dtor(&tmp_val);
        !          1936:                        }
        !          1937: 
        !          1938:                        zend_hash_move_forward(Z_ARRVAL_P(pv_param_arr));
        !          1939:                }
        !          1940:        }
        !          1941: 
        !          1942:        pgsql_result = PQexecPrepared(pgsql, stmtname, num_params, 
        !          1943:                                        (const char * const *)params, NULL, NULL, 0);
        !          1944:        if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
        !          1945:                PQclear(pgsql_result);
        !          1946:                PQreset(pgsql);
        !          1947:                pgsql_result = PQexecPrepared(pgsql, stmtname, num_params, 
        !          1948:                                                (const char * const *)params, NULL, NULL, 0);
        !          1949:        }
        !          1950: 
        !          1951:        if (pgsql_result) {
        !          1952:                status = PQresultStatus(pgsql_result);
        !          1953:        } else {
        !          1954:                status = (ExecStatusType) PQstatus(pgsql);
        !          1955:        }
        !          1956:        
        !          1957:        _php_pgsql_free_params(params, num_params);
        !          1958: 
        !          1959:        switch (status) {
        !          1960:                case PGRES_EMPTY_QUERY:
        !          1961:                case PGRES_BAD_RESPONSE:
        !          1962:                case PGRES_NONFATAL_ERROR:
        !          1963:                case PGRES_FATAL_ERROR:
        !          1964:                        PHP_PQ_ERROR("Query failed: %s", pgsql);
        !          1965:                        PQclear(pgsql_result);
        !          1966:                        RETURN_FALSE;
        !          1967:                        break;
        !          1968:                case PGRES_COMMAND_OK: /* successful command that did not return rows */
        !          1969:                default:
        !          1970:                        if (pgsql_result) {
        !          1971:                                pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle));
        !          1972:                                pg_result->conn = pgsql;
        !          1973:                                pg_result->result = pgsql_result;
        !          1974:                                pg_result->row = 0;
        !          1975:                                ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result);
        !          1976:                        } else {
        !          1977:                                PQclear(pgsql_result);
        !          1978:                                RETURN_FALSE;
        !          1979:                        }
        !          1980:                        break;
        !          1981:        }
        !          1982: }
        !          1983: /* }}} */
        !          1984: #endif
        !          1985: 
        !          1986: #define PHP_PG_NUM_ROWS 1
        !          1987: #define PHP_PG_NUM_FIELDS 2
        !          1988: #define PHP_PG_CMD_TUPLES 3
        !          1989: 
        !          1990: /* {{{ php_pgsql_get_result_info
        !          1991:  */
        !          1992: static void php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
        !          1993: {
        !          1994:        zval *result;
        !          1995:        PGresult *pgsql_result;
        !          1996:        pgsql_result_handle *pg_result;
        !          1997: 
        !          1998:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) {
        !          1999:                return;
        !          2000:        }
        !          2001:        
        !          2002:        ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
        !          2003: 
        !          2004:        pgsql_result = pg_result->result;
        !          2005: 
        !          2006:        switch (entry_type) {
        !          2007:                case PHP_PG_NUM_ROWS:
        !          2008:                        Z_LVAL_P(return_value) = PQntuples(pgsql_result);
        !          2009:                        break;
        !          2010:                case PHP_PG_NUM_FIELDS:
        !          2011:                        Z_LVAL_P(return_value) = PQnfields(pgsql_result);
        !          2012:                        break;
        !          2013:                case PHP_PG_CMD_TUPLES:
        !          2014: #if HAVE_PQCMDTUPLES
        !          2015:                        Z_LVAL_P(return_value) = atoi(PQcmdTuples(pgsql_result));
        !          2016: #else
        !          2017:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not supported under this build");
        !          2018:                        Z_LVAL_P(return_value) = 0;
        !          2019: #endif
        !          2020:                        break;
        !          2021:                default:
        !          2022:                        RETURN_FALSE;
        !          2023:        }
        !          2024:        Z_TYPE_P(return_value) = IS_LONG;
        !          2025: }
        !          2026: /* }}} */
        !          2027: 
        !          2028: /* {{{ proto int pg_num_rows(resource result)
        !          2029:    Return the number of rows in the result */
        !          2030: PHP_FUNCTION(pg_num_rows)
        !          2031: {
        !          2032:        php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_NUM_ROWS);
        !          2033: }
        !          2034: /* }}} */
        !          2035: 
        !          2036: /* {{{ proto int pg_num_fields(resource result)
        !          2037:    Return the number of fields in the result */
        !          2038: PHP_FUNCTION(pg_num_fields)
        !          2039: {
        !          2040:        php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_NUM_FIELDS);
        !          2041: }
        !          2042: /* }}} */
        !          2043: 
        !          2044: #if HAVE_PQCMDTUPLES
        !          2045: /* {{{ proto int pg_affected_rows(resource result)
        !          2046:    Returns the number of affected tuples */
        !          2047: PHP_FUNCTION(pg_affected_rows)
        !          2048: {
        !          2049:        php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_CMD_TUPLES);
        !          2050: }
        !          2051: /* }}} */
        !          2052: #endif
        !          2053: 
        !          2054: /* {{{ proto string pg_last_notice(resource connection)
        !          2055:    Returns the last notice set by the backend */
        !          2056: PHP_FUNCTION(pg_last_notice) 
        !          2057: {
        !          2058:        zval *pgsql_link;
        !          2059:        PGconn *pg_link;
        !          2060:        int id = -1;
        !          2061:        php_pgsql_notice **notice;
        !          2062:        
        !          2063:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pgsql_link) == FAILURE) {
        !          2064:                return;
        !          2065:        }
        !          2066:        /* Just to check if user passed valid resoruce */
        !          2067:        ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          2068: 
        !          2069:        if (zend_hash_index_find(&PGG(notices), Z_RESVAL_P(pgsql_link), (void **)&notice) == FAILURE) {
        !          2070:                RETURN_FALSE;
        !          2071:        }
        !          2072:        RETURN_STRINGL((*notice)->message, (*notice)->len, 1);
        !          2073: }
        !          2074: /* }}} */
        !          2075: 
        !          2076: /* {{{ get_field_name
        !          2077:  */
        !          2078: static char *get_field_name(PGconn *pgsql, Oid oid, HashTable *list TSRMLS_DC)
        !          2079: {
        !          2080:        PGresult *result;
        !          2081:        smart_str str = {0};
        !          2082:        zend_rsrc_list_entry *field_type;
        !          2083:        char *ret=NULL;
        !          2084: 
        !          2085:        /* try to lookup the type in the resource list */
        !          2086:        smart_str_appends(&str, "pgsql_oid_");
        !          2087:        smart_str_append_unsigned(&str, oid);
        !          2088:        smart_str_0(&str);
        !          2089: 
        !          2090:        if (zend_hash_find(list,str.c,str.len+1,(void **) &field_type)==SUCCESS) {
        !          2091:                ret = estrdup((char *)field_type->ptr);
        !          2092:        } else { /* hash all oid's */
        !          2093:                int i,num_rows;
        !          2094:                int oid_offset,name_offset;
        !          2095:                char *tmp_oid, *end_ptr, *tmp_name;
        !          2096:                zend_rsrc_list_entry new_oid_entry;
        !          2097: 
        !          2098:                if ((result = PQexec(pgsql,"select oid,typname from pg_type")) == NULL || PQresultStatus(result) != PGRES_TUPLES_OK) {
        !          2099:                        if (result) {
        !          2100:                                PQclear(result);
        !          2101:                        }
        !          2102:                        smart_str_free(&str);
        !          2103:                        return STR_EMPTY_ALLOC();
        !          2104:                }
        !          2105:                num_rows = PQntuples(result);
        !          2106:                oid_offset = PQfnumber(result,"oid");
        !          2107:                name_offset = PQfnumber(result,"typname");
        !          2108:                
        !          2109:                for (i=0; i<num_rows; i++) {
        !          2110:                        if ((tmp_oid = PQgetvalue(result,i,oid_offset))==NULL) {
        !          2111:                                continue;
        !          2112:                        }
        !          2113:                        
        !          2114:                        str.len = 0;
        !          2115:                        smart_str_appends(&str, "pgsql_oid_");
        !          2116:                        smart_str_appends(&str, tmp_oid);
        !          2117:                        smart_str_0(&str);
        !          2118:        
        !          2119:                        if ((tmp_name = PQgetvalue(result,i,name_offset))==NULL) {
        !          2120:                                continue;
        !          2121:                        }
        !          2122:                        Z_TYPE(new_oid_entry) = le_string;
        !          2123:                        new_oid_entry.ptr = estrdup(tmp_name);
        !          2124:                        zend_hash_update(list,str.c,str.len+1,(void *) &new_oid_entry, sizeof(zend_rsrc_list_entry), NULL);
        !          2125:                        if (!ret && strtoul(tmp_oid, &end_ptr, 10)==oid) {
        !          2126:                                ret = estrdup(tmp_name);
        !          2127:                        }
        !          2128:                }
        !          2129:                PQclear(result);
        !          2130:        }
        !          2131: 
        !          2132:        smart_str_free(&str);
        !          2133:        return ret;
        !          2134: }
        !          2135: /* }}} */                      
        !          2136: 
        !          2137: #ifdef HAVE_PQFTABLE
        !          2138: /* {{{ proto mixed pg_field_table(resource result, int field_number[, bool oid_only])
        !          2139:    Returns the name of the table field belongs to, or table's oid if oid_only is true */
        !          2140: PHP_FUNCTION(pg_field_table)
        !          2141: {
        !          2142:        zval *result;
        !          2143:        pgsql_result_handle *pg_result;
        !          2144:        long fnum = -1;
        !          2145:        zend_bool return_oid = 0;
        !          2146:        Oid oid;
        !          2147:        smart_str hash_key = {0};
        !          2148:        char *table_name;
        !          2149:        zend_rsrc_list_entry *field_table;
        !          2150: 
        !          2151:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|b", &result, &fnum, &return_oid) == FAILURE) {
        !          2152:                return;
        !          2153:        }
        !          2154: 
        !          2155:        ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
        !          2156: 
        !          2157:        if (fnum < 0 || fnum >= PQnfields(pg_result->result)) {
        !          2158:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad field offset specified");
        !          2159:                RETURN_FALSE;
        !          2160:        }
        !          2161: 
        !          2162:        oid = PQftable(pg_result->result, fnum);
        !          2163: 
        !          2164:        if (InvalidOid == oid) {
        !          2165:                RETURN_FALSE;
        !          2166:        }
        !          2167: 
        !          2168: 
        !          2169:        if (return_oid) {
        !          2170: #if UINT_MAX > LONG_MAX /* Oid is unsigned int, we don't need this code, where LONG is wider */
        !          2171:                if (oid > LONG_MAX) {
        !          2172:                        smart_str oidstr = {0};
        !          2173:                        smart_str_append_unsigned(&oidstr, oid);
        !          2174:                        smart_str_0(&oidstr);
        !          2175:                        RETURN_STRINGL(oidstr.c, oidstr.len, 0);
        !          2176:                } else
        !          2177: #endif
        !          2178:                        RETURN_LONG((long)oid);
        !          2179:        }
        !          2180: 
        !          2181:        /* try to lookup the table name in the resource list */
        !          2182:        smart_str_appends(&hash_key, "pgsql_table_oid_");
        !          2183:        smart_str_append_unsigned(&hash_key, oid);
        !          2184:        smart_str_0(&hash_key);
        !          2185: 
        !          2186:        if (zend_hash_find(&EG(regular_list), hash_key.c, hash_key.len+1, (void **) &field_table) == SUCCESS) {
        !          2187:                smart_str_free(&hash_key);
        !          2188:                RETURN_STRING((char *)field_table->ptr, 1);
        !          2189:        } else { /* Not found, lookup by querying PostgreSQL system tables */
        !          2190:                PGresult *tmp_res;
        !          2191:                smart_str querystr = {0};
        !          2192:                zend_rsrc_list_entry new_field_table;
        !          2193: 
        !          2194:                smart_str_appends(&querystr, "select relname from pg_class where oid=");
        !          2195:                smart_str_append_unsigned(&querystr, oid);
        !          2196:                smart_str_0(&querystr);
        !          2197: 
        !          2198: 
        !          2199:                if ((tmp_res = PQexec(pg_result->conn, querystr.c)) == NULL || PQresultStatus(tmp_res) != PGRES_TUPLES_OK) {
        !          2200:                        if (tmp_res) {
        !          2201:                                PQclear(tmp_res);
        !          2202:                        }
        !          2203:                        smart_str_free(&querystr);
        !          2204:                        smart_str_free(&hash_key);
        !          2205:                        RETURN_FALSE;
        !          2206:                }
        !          2207: 
        !          2208:                smart_str_free(&querystr);
        !          2209: 
        !          2210:                if ((table_name = PQgetvalue(tmp_res, 0, 0)) == NULL) {
        !          2211:                        PQclear(tmp_res);
        !          2212:                        smart_str_free(&hash_key);
        !          2213:                        RETURN_FALSE;
        !          2214:                }
        !          2215: 
        !          2216:                Z_TYPE(new_field_table) = le_string;
        !          2217:                new_field_table.ptr = estrdup(table_name);
        !          2218:                zend_hash_update(&EG(regular_list), hash_key.c, hash_key.len+1, (void *) &new_field_table, sizeof(zend_rsrc_list_entry), NULL);
        !          2219: 
        !          2220:                smart_str_free(&hash_key);
        !          2221:                PQclear(tmp_res);
        !          2222:                RETURN_STRING(table_name, 1);
        !          2223:        }
        !          2224: 
        !          2225: }
        !          2226: /* }}} */      
        !          2227: #endif         
        !          2228: 
        !          2229: #define PHP_PG_FIELD_NAME 1
        !          2230: #define PHP_PG_FIELD_SIZE 2
        !          2231: #define PHP_PG_FIELD_TYPE 3
        !          2232: #define PHP_PG_FIELD_TYPE_OID 4
        !          2233: 
        !          2234: /* {{{ php_pgsql_get_field_info
        !          2235:  */
        !          2236: static void php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
        !          2237: {
        !          2238:        zval *result;
        !          2239:        long field;
        !          2240:        PGresult *pgsql_result;
        !          2241:        pgsql_result_handle *pg_result;
        !          2242:        Oid oid;
        !          2243:        
        !          2244:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &result, &field) == FAILURE) {
        !          2245:                return;
        !          2246:        }
        !          2247:        
        !          2248:        ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
        !          2249: 
        !          2250:        pgsql_result = pg_result->result;
        !          2251:        
        !          2252:        if (field < 0 || field >= PQnfields(pgsql_result)) {
        !          2253:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad field offset specified");
        !          2254:                RETURN_FALSE;
        !          2255:        }
        !          2256:        
        !          2257:        switch (entry_type) {
        !          2258:                case PHP_PG_FIELD_NAME:
        !          2259:                        Z_STRVAL_P(return_value) = PQfname(pgsql_result, field);
        !          2260:                        Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
        !          2261:                        Z_STRVAL_P(return_value) = estrndup(Z_STRVAL_P(return_value),Z_STRLEN_P(return_value));
        !          2262:                        Z_TYPE_P(return_value) = IS_STRING;
        !          2263:                        break;
        !          2264:                case PHP_PG_FIELD_SIZE:
        !          2265:                        Z_LVAL_P(return_value) = PQfsize(pgsql_result, field);
        !          2266:                        Z_TYPE_P(return_value) = IS_LONG;
        !          2267:                        break;
        !          2268:                case PHP_PG_FIELD_TYPE:
        !          2269:                        Z_STRVAL_P(return_value) = get_field_name(pg_result->conn, PQftype(pgsql_result, field), &EG(regular_list) TSRMLS_CC);
        !          2270:                        Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
        !          2271:                        Z_TYPE_P(return_value) = IS_STRING;
        !          2272:                        break;
        !          2273:                case PHP_PG_FIELD_TYPE_OID:
        !          2274:                        
        !          2275:                        oid = PQftype(pgsql_result, field);
        !          2276: #if UINT_MAX > LONG_MAX
        !          2277:                        if (oid > LONG_MAX) {
        !          2278:                                smart_str s = {0};
        !          2279:                                smart_str_append_unsigned(&s, oid);
        !          2280:                                smart_str_0(&s);
        !          2281:                                Z_STRVAL_P(return_value) = s.c;
        !          2282:                                Z_STRLEN_P(return_value) = s.len;
        !          2283:                                Z_TYPE_P(return_value) = IS_STRING;
        !          2284:                        } else
        !          2285: #endif
        !          2286:                        {
        !          2287:                                Z_LVAL_P(return_value) = (long)oid;
        !          2288:                                Z_TYPE_P(return_value) = IS_LONG;
        !          2289:                        }
        !          2290:                        break;
        !          2291:                default:
        !          2292:                        RETURN_FALSE;
        !          2293:        }
        !          2294: }
        !          2295: /* }}} */
        !          2296: 
        !          2297: /* {{{ proto string pg_field_name(resource result, int field_number)
        !          2298:    Returns the name of the field */
        !          2299: PHP_FUNCTION(pg_field_name)
        !          2300: {
        !          2301:        php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_FIELD_NAME);
        !          2302: }
        !          2303: /* }}} */
        !          2304: 
        !          2305: /* {{{ proto int pg_field_size(resource result, int field_number)
        !          2306:    Returns the internal size of the field */ 
        !          2307: PHP_FUNCTION(pg_field_size)
        !          2308: {
        !          2309:        php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_FIELD_SIZE);
        !          2310: }
        !          2311: /* }}} */
        !          2312: 
        !          2313: /* {{{ proto string pg_field_type(resource result, int field_number)
        !          2314:    Returns the type name for the given field */
        !          2315: PHP_FUNCTION(pg_field_type)
        !          2316: {
        !          2317:        php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_FIELD_TYPE);
        !          2318: }
        !          2319: /* }}} */
        !          2320: 
        !          2321: 
        !          2322: /* {{{ proto string pg_field_type_oid(resource result, int field_number)
        !          2323:    Returns the type oid for the given field */
        !          2324: PHP_FUNCTION(pg_field_type_oid)
        !          2325: {
        !          2326:        php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_FIELD_TYPE_OID);
        !          2327: }
        !          2328: /* }}} */
        !          2329: 
        !          2330: /* {{{ proto int pg_field_num(resource result, string field_name)
        !          2331:    Returns the field number of the named field */
        !          2332: PHP_FUNCTION(pg_field_num)
        !          2333: {
        !          2334:        zval *result;
        !          2335:        char *field;
        !          2336:        int field_len;
        !          2337:        PGresult *pgsql_result;
        !          2338:        pgsql_result_handle *pg_result;
        !          2339: 
        !          2340:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &result, &field, &field_len) == FAILURE) {
        !          2341:                return;
        !          2342:        }
        !          2343:        
        !          2344:        ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
        !          2345: 
        !          2346:        pgsql_result = pg_result->result;
        !          2347:        
        !          2348:        Z_LVAL_P(return_value) = PQfnumber(pgsql_result, field);
        !          2349:        Z_TYPE_P(return_value) = IS_LONG;
        !          2350: }
        !          2351: /* }}} */
        !          2352: 
        !          2353: /* {{{ proto mixed pg_fetch_result(resource result, [int row_number,] mixed field_name)
        !          2354:    Returns values from a result identifier */
        !          2355: PHP_FUNCTION(pg_fetch_result)
        !          2356: {
        !          2357:        zval *result, **field=NULL;
        !          2358:        long row;
        !          2359:        PGresult *pgsql_result;
        !          2360:        pgsql_result_handle *pg_result;
        !          2361:        int field_offset, pgsql_row, argc = ZEND_NUM_ARGS();
        !          2362:        
        !          2363:        if (argc == 2) {
        !          2364:                if (zend_parse_parameters(argc TSRMLS_CC, "rZ", &result, &field) == FAILURE) {
        !          2365:                        return;
        !          2366:                }
        !          2367:        } else {
        !          2368:                if (zend_parse_parameters(argc TSRMLS_CC, "rlZ", &result, &row, &field) == FAILURE) {
        !          2369:                        return;
        !          2370:                }
        !          2371:        }
        !          2372:        
        !          2373:        ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
        !          2374: 
        !          2375:        pgsql_result = pg_result->result;
        !          2376:        if (argc == 2) {
        !          2377:                if (pg_result->row < 0) {
        !          2378:                        pg_result->row = 0;
        !          2379:                }
        !          2380:                pgsql_row = pg_result->row;
        !          2381:                if (pgsql_row >= PQntuples(pgsql_result)) {
        !          2382:                        RETURN_FALSE;
        !          2383:                }
        !          2384:        } else {
        !          2385:                pgsql_row = row;
        !          2386:                if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
        !          2387:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to jump to row %ld on PostgreSQL result index %ld",
        !          2388:                                                        row, Z_LVAL_P(result));
        !          2389:                        RETURN_FALSE;
        !          2390:                }
        !          2391:        }
        !          2392:        switch(Z_TYPE_PP(field)) {
        !          2393:                case IS_STRING:
        !          2394:                        field_offset = PQfnumber(pgsql_result, Z_STRVAL_PP(field));
        !          2395:                        break;
        !          2396:                default:
        !          2397:                        convert_to_long_ex(field);
        !          2398:                        field_offset = Z_LVAL_PP(field);
        !          2399:                        break;
        !          2400:        }
        !          2401:        if (field_offset<0 || field_offset>=PQnfields(pgsql_result)) {
        !          2402:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset specified");
        !          2403:                RETURN_FALSE;
        !          2404:        }
        !          2405:        
        !          2406:        if (PQgetisnull(pgsql_result, pgsql_row, field_offset)) {
        !          2407:                Z_TYPE_P(return_value) = IS_NULL;
        !          2408:        } else {
        !          2409:                char *value = PQgetvalue(pgsql_result, pgsql_row, field_offset);
        !          2410:                int value_len = PQgetlength(pgsql_result, pgsql_row, field_offset);
        !          2411:                ZVAL_STRINGL(return_value, value, value_len, 1);
        !          2412:        }
        !          2413: }
        !          2414: /* }}} */
        !          2415: 
        !          2416: /* {{{ void php_pgsql_fetch_hash */
        !          2417: static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, long result_type, int into_object)
        !          2418: {
        !          2419:        zval                *result, *zrow = NULL;
        !          2420:        PGresult            *pgsql_result;
        !          2421:        pgsql_result_handle *pg_result;
        !          2422:        int             i, num_fields, pgsql_row, use_row;
        !          2423:        long            row = -1;
        !          2424:        char            *field_name;
        !          2425:        zval            *ctor_params = NULL;
        !          2426:        zend_class_entry *ce = NULL;
        !          2427: 
        !          2428:        if (into_object) {
        !          2429:                char *class_name = NULL;
        !          2430:                int class_name_len;
        !          2431: 
        !          2432:                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|z!sz", &result, &zrow, &class_name, &class_name_len, &ctor_params) == FAILURE) {
        !          2433:                        return;
        !          2434:                }
        !          2435:                if (!class_name) {
        !          2436:                        ce = zend_standard_class_def;
        !          2437:                } else {
        !          2438:                        ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
        !          2439:                }
        !          2440:                if (!ce) {
        !          2441:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not find class '%s'", class_name);
        !          2442:                        return;
        !          2443:                }
        !          2444:                result_type = PGSQL_ASSOC;
        !          2445:        } else {
        !          2446:                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|z!l", &result, &zrow, &result_type) == FAILURE) {
        !          2447:                        return;
        !          2448:                }
        !          2449:        }
        !          2450:        if (zrow == NULL) {
        !          2451:                row = -1;
        !          2452:        } else {
        !          2453:                convert_to_long(zrow);
        !          2454:                row = Z_LVAL_P(zrow);
        !          2455:                if (row < 0) {
        !          2456:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "The row parameter must be greater or equal to zero");
        !          2457:                        RETURN_FALSE;
        !          2458:                }
        !          2459:        }
        !          2460:        use_row = ZEND_NUM_ARGS() > 1 && row != -1;
        !          2461: 
        !          2462:        if (!(result_type & PGSQL_BOTH)) {
        !          2463:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid result type");
        !          2464:                RETURN_FALSE;
        !          2465:        }
        !          2466:        
        !          2467:        ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
        !          2468: 
        !          2469:        pgsql_result = pg_result->result;
        !          2470: 
        !          2471:        if (use_row) { 
        !          2472:                pgsql_row = row;
        !          2473:                pg_result->row = pgsql_row;
        !          2474:                if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
        !          2475:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to jump to row %ld on PostgreSQL result index %ld",
        !          2476:                                                        row, Z_LVAL_P(result));
        !          2477:                        RETURN_FALSE;
        !          2478:                }
        !          2479:        } else {
        !          2480:                /* If 2nd param is NULL, use internal row counter to access next row */
        !          2481:                pgsql_row = pg_result->row;
        !          2482:                if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
        !          2483:                        RETURN_FALSE;
        !          2484:                }
        !          2485:                pg_result->row++;
        !          2486:        }
        !          2487: 
        !          2488:        array_init(return_value);
        !          2489:        for (i = 0, num_fields = PQnfields(pgsql_result); i < num_fields; i++) {
        !          2490:                if (PQgetisnull(pgsql_result, pgsql_row, i)) {
        !          2491:                        if (result_type & PGSQL_NUM) {
        !          2492:                                add_index_null(return_value, i);
        !          2493:                        }
        !          2494:                        if (result_type & PGSQL_ASSOC) {
        !          2495:                                field_name = PQfname(pgsql_result, i);
        !          2496:                                add_assoc_null(return_value, field_name);
        !          2497:                        }
        !          2498:                } else {
        !          2499:                        char *element = PQgetvalue(pgsql_result, pgsql_row, i);
        !          2500:                        if (element) {
        !          2501:                                char *data;
        !          2502:                                int data_len;
        !          2503:                                int should_copy=0;
        !          2504:                                const uint element_len = strlen(element);
        !          2505: 
        !          2506:                                if (PG(magic_quotes_runtime)) {
        !          2507:                                        data = php_addslashes(element, element_len, &data_len, 0 TSRMLS_CC);
        !          2508:                                } else {
        !          2509:                                        data = safe_estrndup(element, element_len);
        !          2510:                                        data_len = element_len;
        !          2511:                                }
        !          2512:                        
        !          2513:                                if (result_type & PGSQL_NUM) {
        !          2514:                                        add_index_stringl(return_value, i, data, data_len, should_copy);
        !          2515:                                        should_copy=1;
        !          2516:                                }
        !          2517:                        
        !          2518:                                if (result_type & PGSQL_ASSOC) {
        !          2519:                                        field_name = PQfname(pgsql_result, i);
        !          2520:                                        add_assoc_stringl(return_value, field_name, data, data_len, should_copy);
        !          2521:                                }
        !          2522:                        }
        !          2523:                }
        !          2524:        }
        !          2525: 
        !          2526:        if (into_object) {
        !          2527:                zval dataset = *return_value;
        !          2528:                zend_fcall_info fci;
        !          2529:                zend_fcall_info_cache fcc;
        !          2530:                zval *retval_ptr; 
        !          2531:        
        !          2532:                object_and_properties_init(return_value, ce, NULL);
        !          2533:                zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC);
        !          2534:        
        !          2535:                if (ce->constructor) {
        !          2536:                        fci.size = sizeof(fci);
        !          2537:                        fci.function_table = &ce->function_table;
        !          2538:                        fci.function_name = NULL;
        !          2539:                        fci.symbol_table = NULL;
        !          2540:                        fci.object_ptr = return_value;
        !          2541:                        fci.retval_ptr_ptr = &retval_ptr;
        !          2542:                        if (ctor_params && Z_TYPE_P(ctor_params) != IS_NULL) {
        !          2543:                                if (Z_TYPE_P(ctor_params) == IS_ARRAY) {
        !          2544:                                        HashTable *ht = Z_ARRVAL_P(ctor_params);
        !          2545:                                        Bucket *p;
        !          2546:        
        !          2547:                                        fci.param_count = 0;
        !          2548:                                        fci.params = safe_emalloc(sizeof(zval*), ht->nNumOfElements, 0);
        !          2549:                                        p = ht->pListHead;
        !          2550:                                        while (p != NULL) {
        !          2551:                                                fci.params[fci.param_count++] = (zval**)p->pData;
        !          2552:                                                p = p->pListNext;
        !          2553:                                        }
        !          2554:                                } else {
        !          2555:                                        /* Two problems why we throw exceptions here: PHP is typeless
        !          2556:                                         * and hence passing one argument that's not an array could be
        !          2557:                                         * by mistake and the other way round is possible, too. The 
        !          2558:                                         * single value is an array. Also we'd have to make that one
        !          2559:                                         * argument passed by reference.
        !          2560:                                         */
        !          2561:                                        zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Parameter ctor_params must be an array", 0 TSRMLS_CC);
        !          2562:                                        return;
        !          2563:                                }
        !          2564:                        } else {
        !          2565:                                fci.param_count = 0;
        !          2566:                                fci.params = NULL;
        !          2567:                        }
        !          2568:                        fci.no_separation = 1;
        !          2569: 
        !          2570:                        fcc.initialized = 1;
        !          2571:                        fcc.function_handler = ce->constructor;
        !          2572:                        fcc.calling_scope = EG(scope);
        !          2573:                        fcc.called_scope = Z_OBJCE_P(return_value);
        !          2574:                        fcc.object_ptr = return_value;
        !          2575:                
        !          2576:                        if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
        !          2577:                                zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Could not execute %s::%s()", ce->name, ce->constructor->common.function_name);
        !          2578:                        } else {
        !          2579:                                if (retval_ptr) {
        !          2580:                                        zval_ptr_dtor(&retval_ptr);
        !          2581:                                }
        !          2582:                        }
        !          2583:                        if (fci.params) {
        !          2584:                                efree(fci.params);
        !          2585:                        }
        !          2586:                } else if (ctor_params) {
        !          2587:                        zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Class %s does not have a constructor hence you cannot use ctor_params", ce->name);
        !          2588:                }
        !          2589:        }
        !          2590: }
        !          2591: /* }}} */
        !          2592: 
        !          2593: /* {{{ proto array pg_fetch_row(resource result [, int row [, int result_type]])
        !          2594:    Get a row as an enumerated array */ 
        !          2595: PHP_FUNCTION(pg_fetch_row)
        !          2596: {
        !          2597:        php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_NUM, 0);
        !          2598: }
        !          2599: /* }}} */
        !          2600: 
        !          2601: /* {{{ proto array pg_fetch_assoc(resource result [, int row])
        !          2602:    Fetch a row as an assoc array */
        !          2603: PHP_FUNCTION(pg_fetch_assoc)
        !          2604: {
        !          2605:        /* pg_fetch_assoc() is added from PHP 4.3.0. It should raise error, when
        !          2606:           there is 3rd parameter */
        !          2607:        if (ZEND_NUM_ARGS() > 2)
        !          2608:                WRONG_PARAM_COUNT;
        !          2609:        php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_ASSOC, 0);
        !          2610: }
        !          2611: /* }}} */
        !          2612: 
        !          2613: /* {{{ proto array pg_fetch_array(resource result [, int row [, int result_type]])
        !          2614:    Fetch a row as an array */
        !          2615: PHP_FUNCTION(pg_fetch_array)
        !          2616: {
        !          2617:        php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_BOTH, 0);
        !          2618: }
        !          2619: /* }}} */
        !          2620: 
        !          2621: /* {{{ proto object pg_fetch_object(resource result [, int row [, string class_name [, NULL|array ctor_params]]])
        !          2622:    Fetch a row as an object */
        !          2623: PHP_FUNCTION(pg_fetch_object)
        !          2624: {
        !          2625:        /* pg_fetch_object() allowed result_type used to be. 3rd parameter
        !          2626:           must be allowed for compatibility */
        !          2627:        php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_ASSOC, 1);
        !          2628: }
        !          2629: /* }}} */
        !          2630: 
        !          2631: /* {{{ proto array pg_fetch_all(resource result)
        !          2632:    Fetch all rows into array */
        !          2633: PHP_FUNCTION(pg_fetch_all)
        !          2634: {
        !          2635:        zval *result;
        !          2636:        PGresult *pgsql_result;
        !          2637:        pgsql_result_handle *pg_result;
        !          2638: 
        !          2639:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) {
        !          2640:                return;
        !          2641:        }
        !          2642: 
        !          2643:        ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
        !          2644: 
        !          2645:        pgsql_result = pg_result->result;
        !          2646:        array_init(return_value);
        !          2647:        if (php_pgsql_result2array(pgsql_result, return_value TSRMLS_CC) == FAILURE) {
        !          2648:                zval_dtor(return_value);
        !          2649:                RETURN_FALSE;
        !          2650:        }
        !          2651: }
        !          2652: /* }}} */
        !          2653: 
        !          2654: /* {{{ proto array pg_fetch_all_columns(resource result [, int column_number])
        !          2655:    Fetch all rows into array */
        !          2656: PHP_FUNCTION(pg_fetch_all_columns)
        !          2657: {
        !          2658:        zval *result;
        !          2659:        PGresult *pgsql_result;
        !          2660:        pgsql_result_handle *pg_result;
        !          2661:        unsigned long colno=0;
        !          2662:        int pg_numrows, pg_row;
        !          2663:        size_t num_fields;
        !          2664: 
        !          2665:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &result, &colno) == FAILURE) {
        !          2666:                RETURN_FALSE;
        !          2667:        }
        !          2668: 
        !          2669:        ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
        !          2670: 
        !          2671:        pgsql_result = pg_result->result;
        !          2672: 
        !          2673:        num_fields = PQnfields(pgsql_result);
        !          2674:        if (colno >= num_fields || colno < 0) {
        !          2675:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid column number '%ld'", colno);
        !          2676:                RETURN_FALSE;
        !          2677:        }
        !          2678: 
        !          2679:        array_init(return_value);
        !          2680: 
        !          2681:         if ((pg_numrows = PQntuples(pgsql_result)) <= 0) {
        !          2682:                return;
        !          2683:        }
        !          2684: 
        !          2685:        for (pg_row = 0; pg_row < pg_numrows; pg_row++) {
        !          2686:                if (PQgetisnull(pgsql_result, pg_row, colno)) {
        !          2687:                        add_next_index_null(return_value);
        !          2688:                } else {
        !          2689:                        add_next_index_string(return_value, PQgetvalue(pgsql_result, pg_row, colno), 1); 
        !          2690:                }               
        !          2691:        }
        !          2692: }
        !          2693: /* }}} */
        !          2694: 
        !          2695: /* {{{ proto bool pg_result_seek(resource result, int offset)
        !          2696:    Set internal row offset */
        !          2697: PHP_FUNCTION(pg_result_seek)
        !          2698: {
        !          2699:        zval *result;
        !          2700:        long row;
        !          2701:        pgsql_result_handle *pg_result;
        !          2702: 
        !          2703:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &result, &row) == FAILURE) {
        !          2704:                return;
        !          2705:        }
        !          2706: 
        !          2707:        ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
        !          2708: 
        !          2709:        if (row < 0 || row >= PQntuples(pg_result->result)) {
        !          2710:                RETURN_FALSE;
        !          2711:        }
        !          2712:        
        !          2713:        /* seek to offset */
        !          2714:        pg_result->row = row;
        !          2715:        RETURN_TRUE;
        !          2716: }
        !          2717: /* }}} */
        !          2718: 
        !          2719: 
        !          2720: #define PHP_PG_DATA_LENGTH 1
        !          2721: #define PHP_PG_DATA_ISNULL 2
        !          2722: 
        !          2723: /* {{{ php_pgsql_data_info
        !          2724:  */
        !          2725: static void php_pgsql_data_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
        !          2726: {
        !          2727:        zval *result, **field;
        !          2728:        long row;
        !          2729:        PGresult *pgsql_result;
        !          2730:        pgsql_result_handle *pg_result;
        !          2731:        int field_offset, pgsql_row, argc = ZEND_NUM_ARGS();
        !          2732: 
        !          2733:        if (argc == 2) {
        !          2734:                if (zend_parse_parameters(argc TSRMLS_CC, "rZ", &result, &field) == FAILURE) {
        !          2735:                        return;
        !          2736:                }
        !          2737:        } else {
        !          2738:                if (zend_parse_parameters(argc TSRMLS_CC, "rlZ", &result, &row, &field) == FAILURE) {
        !          2739:                        return;
        !          2740:                }
        !          2741:        }
        !          2742:        
        !          2743:        ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
        !          2744: 
        !          2745:        pgsql_result = pg_result->result;
        !          2746:        if (argc == 2) {
        !          2747:                if (pg_result->row < 0) {
        !          2748:                        pg_result->row = 0;
        !          2749:                }
        !          2750:                pgsql_row = pg_result->row;
        !          2751:                if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
        !          2752:                        RETURN_FALSE;
        !          2753:                }
        !          2754:        } else {
        !          2755:                pgsql_row = row;
        !          2756:                if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
        !          2757:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to jump to row %ld on PostgreSQL result index %ld",
        !          2758:                                                        row, Z_LVAL_P(result));
        !          2759:                        RETURN_FALSE;
        !          2760:                }
        !          2761:        }
        !          2762:        
        !          2763:        switch(Z_TYPE_PP(field)) {
        !          2764:                case IS_STRING:
        !          2765:                        convert_to_string_ex(field);
        !          2766:                        field_offset = PQfnumber(pgsql_result, Z_STRVAL_PP(field));
        !          2767:                        break;
        !          2768:                default:
        !          2769:                        convert_to_long_ex(field);
        !          2770:                        field_offset = Z_LVAL_PP(field);
        !          2771:                        break;
        !          2772:        }
        !          2773:        if (field_offset < 0 || field_offset >= PQnfields(pgsql_result)) {
        !          2774:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset specified");
        !          2775:                RETURN_FALSE;
        !          2776:        }
        !          2777:        
        !          2778:        switch (entry_type) {
        !          2779:                case PHP_PG_DATA_LENGTH:
        !          2780:                        Z_LVAL_P(return_value) = PQgetlength(pgsql_result, pgsql_row, field_offset);
        !          2781:                        break;
        !          2782:                case PHP_PG_DATA_ISNULL:
        !          2783:                        Z_LVAL_P(return_value) = PQgetisnull(pgsql_result, pgsql_row, field_offset);
        !          2784:                        break;
        !          2785:        }
        !          2786:        Z_TYPE_P(return_value) = IS_LONG;
        !          2787: }
        !          2788: /* }}} */
        !          2789: 
        !          2790: /* {{{ proto int pg_field_prtlen(resource result, [int row,] mixed field_name_or_number)
        !          2791:    Returns the printed length */
        !          2792: PHP_FUNCTION(pg_field_prtlen)
        !          2793: {
        !          2794:        php_pgsql_data_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_DATA_LENGTH);
        !          2795: }
        !          2796: /* }}} */
        !          2797: 
        !          2798: /* {{{ proto int pg_field_is_null(resource result, [int row,] mixed field_name_or_number)
        !          2799:    Test if a field is NULL */
        !          2800: PHP_FUNCTION(pg_field_is_null)
        !          2801: {
        !          2802:        php_pgsql_data_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_DATA_ISNULL);
        !          2803: }
        !          2804: /* }}} */
        !          2805: 
        !          2806: /* {{{ proto bool pg_free_result(resource result)
        !          2807:    Free result memory */
        !          2808: PHP_FUNCTION(pg_free_result)
        !          2809: {
        !          2810:        zval *result;
        !          2811:        pgsql_result_handle *pg_result;
        !          2812:        
        !          2813:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) {
        !          2814:                return;
        !          2815:        }
        !          2816: 
        !          2817:        ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
        !          2818:        if (Z_LVAL_P(result) == 0) {
        !          2819:                RETURN_FALSE;
        !          2820:        }
        !          2821:        zend_list_delete(Z_RESVAL_P(result));
        !          2822:        RETURN_TRUE;
        !          2823: }
        !          2824: /* }}} */
        !          2825: 
        !          2826: /* {{{ proto string pg_last_oid(resource result)
        !          2827:    Returns the last object identifier */
        !          2828: PHP_FUNCTION(pg_last_oid)
        !          2829: {
        !          2830:        zval *result;
        !          2831:        PGresult *pgsql_result;
        !          2832:        pgsql_result_handle *pg_result;
        !          2833: #ifdef HAVE_PQOIDVALUE
        !          2834:        Oid oid;
        !          2835: #endif
        !          2836: 
        !          2837:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) {
        !          2838:                return;
        !          2839:        }
        !          2840:        
        !          2841:        ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
        !          2842:        pgsql_result = pg_result->result;
        !          2843: #ifdef HAVE_PQOIDVALUE
        !          2844:        oid = PQoidValue(pgsql_result);
        !          2845:        if (oid == InvalidOid) {
        !          2846:                RETURN_FALSE;
        !          2847:        }
        !          2848:        PGSQL_RETURN_OID(oid);
        !          2849: #else
        !          2850:        Z_STRVAL_P(return_value) = (char *) PQoidStatus(pgsql_result);
        !          2851:        if (Z_STRVAL_P(return_value)) {
        !          2852:                RETURN_STRING(Z_STRVAL_P(return_value), 1);
        !          2853:        }
        !          2854:        RETURN_STRING("", 1);
        !          2855: #endif
        !          2856: }
        !          2857: /* }}} */
        !          2858: 
        !          2859: /* {{{ proto bool pg_trace(string filename [, string mode [, resource connection]])
        !          2860:    Enable tracing a PostgreSQL connection */
        !          2861: PHP_FUNCTION(pg_trace)
        !          2862: {
        !          2863:        char *z_filename, *mode = "w";
        !          2864:        int z_filename_len, mode_len;
        !          2865:        zval *pgsql_link = NULL;
        !          2866:        int id = -1, argc = ZEND_NUM_ARGS();
        !          2867:        PGconn *pgsql;
        !          2868:        FILE *fp = NULL;
        !          2869:        php_stream *stream;
        !          2870:        id = PGG(default_link);
        !          2871:        
        !          2872:        if (zend_parse_parameters(argc TSRMLS_CC, "s|sr", &z_filename, &z_filename_len, &mode, &mode_len, &pgsql_link) == FAILURE) {
        !          2873:                return;
        !          2874:        }
        !          2875: 
        !          2876:        if (argc < 3) {
        !          2877:                CHECK_DEFAULT_LINK(id);
        !          2878:        }               
        !          2879: 
        !          2880:        if (pgsql_link == NULL && id == -1) {
        !          2881:                RETURN_FALSE;
        !          2882:        }       
        !          2883: 
        !          2884:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          2885: 
        !          2886:        stream = php_stream_open_wrapper(z_filename, mode, ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
        !          2887: 
        !          2888:        if (!stream) {
        !          2889:                RETURN_FALSE;
        !          2890:        }
        !          2891: 
        !          2892:        if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void**)&fp, REPORT_ERRORS))        {
        !          2893:                php_stream_close(stream);
        !          2894:                RETURN_FALSE;
        !          2895:        }
        !          2896:        php_stream_auto_cleanup(stream);
        !          2897:        PQtrace(pgsql, fp);
        !          2898:        RETURN_TRUE;
        !          2899: }
        !          2900: /* }}} */
        !          2901: 
        !          2902: /* {{{ proto bool pg_untrace([resource connection])
        !          2903:    Disable tracing of a PostgreSQL connection */
        !          2904: PHP_FUNCTION(pg_untrace)
        !          2905: {
        !          2906:        zval *pgsql_link = NULL;
        !          2907:        int id = -1, argc = ZEND_NUM_ARGS();
        !          2908:        PGconn *pgsql;
        !          2909:        
        !          2910:        if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) {
        !          2911:                return;
        !          2912:        }
        !          2913: 
        !          2914:        if (argc == 0) { 
        !          2915:                id = PGG(default_link);
        !          2916:                CHECK_DEFAULT_LINK(id);
        !          2917:        }
        !          2918: 
        !          2919:        if (pgsql_link == NULL && id == -1) {
        !          2920:                RETURN_FALSE;
        !          2921:        }       
        !          2922: 
        !          2923:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          2924:        PQuntrace(pgsql);
        !          2925:        RETURN_TRUE;
        !          2926: }
        !          2927: /* }}} */
        !          2928: 
        !          2929: /* {{{ proto mixed pg_lo_create([resource connection],[mixed large_object_oid])
        !          2930:    Create a large object */
        !          2931: PHP_FUNCTION(pg_lo_create)
        !          2932: {
        !          2933:        zval *pgsql_link = NULL, *oid = NULL;
        !          2934:        PGconn *pgsql;
        !          2935:        Oid pgsql_oid, wanted_oid = InvalidOid;
        !          2936:        int id = -1, argc = ZEND_NUM_ARGS();
        !          2937: 
        !          2938:        if (zend_parse_parameters(argc TSRMLS_CC, "|zz", &pgsql_link, &oid) == FAILURE) {
        !          2939:                return;
        !          2940:        }
        !          2941: 
        !          2942:        if ((argc == 1) && (Z_TYPE_P(pgsql_link) != IS_RESOURCE)) {
        !          2943:                oid = pgsql_link;
        !          2944:                pgsql_link = NULL;
        !          2945:        }
        !          2946:        
        !          2947:        if (pgsql_link == NULL) {
        !          2948:                id = PGG(default_link);
        !          2949:                CHECK_DEFAULT_LINK(id);
        !          2950:                if (id == -1) {
        !          2951:                        RETURN_FALSE;
        !          2952:                }
        !          2953:        }
        !          2954: 
        !          2955:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          2956:        
        !          2957:        if (oid) {
        !          2958: #ifndef HAVE_PG_LO_CREATE      
        !          2959:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "OID value passing not supported");
        !          2960: #else
        !          2961:                switch (Z_TYPE_P(oid)) {
        !          2962:                case IS_STRING:
        !          2963:                        {       
        !          2964:                                char *end_ptr;
        !          2965:                                wanted_oid = (Oid)strtoul(Z_STRVAL_P(oid), &end_ptr, 10);
        !          2966:                                if ((Z_STRVAL_P(oid)+Z_STRLEN_P(oid)) != end_ptr) {
        !          2967:                                /* wrong integer format */
        !          2968:                                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
        !          2969:                                RETURN_FALSE;
        !          2970:                                }
        !          2971:                        }
        !          2972:                        break;
        !          2973:                case IS_LONG:
        !          2974:                        if (Z_LVAL_P(oid) < (long)InvalidOid) {
        !          2975:                                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
        !          2976:                                RETURN_FALSE;
        !          2977:                        }
        !          2978:                        wanted_oid = (Oid)Z_LVAL_P(oid);
        !          2979:                        break;
        !          2980:                default:
        !          2981:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
        !          2982:                        RETURN_FALSE;
        !          2983:         }
        !          2984:                if ((pgsql_oid = lo_create(pgsql, wanted_oid)) == InvalidOid) {
        !          2985:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create PostgreSQL large object");
        !          2986:                        RETURN_FALSE;
        !          2987:                }
        !          2988: 
        !          2989:                PGSQL_RETURN_OID(pgsql_oid);    
        !          2990: #endif
        !          2991:        }
        !          2992: 
        !          2993:        if ((pgsql_oid = lo_creat(pgsql, INV_READ|INV_WRITE)) == InvalidOid) {
        !          2994:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create PostgreSQL large object");
        !          2995:                RETURN_FALSE;
        !          2996:        }
        !          2997: 
        !          2998:        PGSQL_RETURN_OID(pgsql_oid);    
        !          2999: }
        !          3000: /* }}} */
        !          3001: 
        !          3002: /* {{{ proto bool pg_lo_unlink([resource connection,] string large_object_oid)
        !          3003:    Delete a large object */
        !          3004: PHP_FUNCTION(pg_lo_unlink)
        !          3005: {
        !          3006:        zval *pgsql_link = NULL;
        !          3007:        long oid_long;
        !          3008:        char *oid_string, *end_ptr;
        !          3009:        int oid_strlen;
        !          3010:        PGconn *pgsql;
        !          3011:        Oid oid;
        !          3012:        int id = -1;
        !          3013:        int argc = ZEND_NUM_ARGS();
        !          3014: 
        !          3015:        /* accept string type since Oid type is unsigned int */
        !          3016:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
        !          3017:                                                                 "rs", &pgsql_link, &oid_string, &oid_strlen) == SUCCESS) {
        !          3018:                oid = (Oid)strtoul(oid_string, &end_ptr, 10);
        !          3019:                if ((oid_string+oid_strlen) != end_ptr) {
        !          3020:                        /* wrong integer format */
        !          3021:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
        !          3022:                        RETURN_FALSE;
        !          3023:                }
        !          3024:        }
        !          3025:        else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
        !          3026:                                                                 "rl", &pgsql_link, &oid_long) == SUCCESS) {
        !          3027:                if (oid_long <= InvalidOid) {
        !          3028:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
        !          3029:                        RETURN_FALSE;
        !          3030:                }
        !          3031:                oid = (Oid)oid_long;
        !          3032:        }
        !          3033:        else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
        !          3034:                                                                 "s", &oid_string, &oid_strlen) == SUCCESS) {
        !          3035:                oid = (Oid)strtoul(oid_string, &end_ptr, 10);
        !          3036:                if ((oid_string+oid_strlen) != end_ptr) {
        !          3037:                        /* wrong integer format */
        !          3038:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
        !          3039:                        RETURN_FALSE;
        !          3040:                }
        !          3041:                id = PGG(default_link);
        !          3042:                CHECK_DEFAULT_LINK(id);
        !          3043:        }
        !          3044:        else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
        !          3045:                                                                 "l", &oid_long) == SUCCESS) {
        !          3046:                if (oid_long <= InvalidOid) {
        !          3047:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID is specified");
        !          3048:                        RETURN_FALSE;
        !          3049:                }
        !          3050:                oid = (Oid)oid_long;
        !          3051:                id = PGG(default_link);
        !          3052:                CHECK_DEFAULT_LINK(id);
        !          3053:        }
        !          3054:        else {
        !          3055:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Requires 1 or 2 arguments");
        !          3056:                RETURN_FALSE;
        !          3057:        }
        !          3058:        if (pgsql_link == NULL && id == -1) {
        !          3059:                RETURN_FALSE;
        !          3060:        }       
        !          3061: 
        !          3062:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          3063: 
        !          3064:        if (lo_unlink(pgsql, oid) == -1) {
        !          3065:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to delete PostgreSQL large object %u", oid);
        !          3066:                RETURN_FALSE;
        !          3067:        }
        !          3068:        RETURN_TRUE;
        !          3069: }
        !          3070: /* }}} */
        !          3071: 
        !          3072: /* {{{ proto resource pg_lo_open([resource connection,] int large_object_oid, string mode)
        !          3073:    Open a large object and return fd */
        !          3074: PHP_FUNCTION(pg_lo_open)
        !          3075: {
        !          3076:        zval *pgsql_link = NULL;
        !          3077:        long oid_long;
        !          3078:        char *oid_string, *end_ptr, *mode_string;
        !          3079:        int oid_strlen, mode_strlen;
        !          3080:        PGconn *pgsql;
        !          3081:        Oid oid;
        !          3082:        int id = -1, pgsql_mode=0, pgsql_lofd;
        !          3083:        int create=0;
        !          3084:        pgLofp *pgsql_lofp;
        !          3085:        int argc = ZEND_NUM_ARGS();
        !          3086: 
        !          3087:        /* accept string type since Oid is unsigned int */
        !          3088:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
        !          3089:                                                                 "rss", &pgsql_link, &oid_string, &oid_strlen, &mode_string, &mode_strlen) == SUCCESS) {
        !          3090:                oid = (Oid)strtoul(oid_string, &end_ptr, 10);
        !          3091:                if ((oid_string+oid_strlen) != end_ptr) {
        !          3092:                        /* wrong integer format */
        !          3093:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
        !          3094:                        RETURN_FALSE;
        !          3095:                }
        !          3096:        }
        !          3097:        else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
        !          3098:                                                                 "rls", &pgsql_link, &oid_long, &mode_string, &mode_strlen) == SUCCESS) {
        !          3099:                if (oid_long <= InvalidOid) {
        !          3100:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
        !          3101:                        RETURN_FALSE;
        !          3102:                }
        !          3103:                oid = (Oid)oid_long;
        !          3104:        }
        !          3105:        else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
        !          3106:                                                                 "ss", &oid_string, &oid_strlen, &mode_string, &mode_strlen) == SUCCESS) {
        !          3107:                oid = (Oid)strtoul(oid_string, &end_ptr, 10);
        !          3108:                if ((oid_string+oid_strlen) != end_ptr) {
        !          3109:                        /* wrong integer format */
        !          3110:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
        !          3111:                        RETURN_FALSE;
        !          3112:                }
        !          3113:                id = PGG(default_link);
        !          3114:                CHECK_DEFAULT_LINK(id);
        !          3115:        }
        !          3116:        else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
        !          3117:                                                                 "ls", &oid_long, &mode_string, &mode_strlen) == SUCCESS) {
        !          3118:                if (oid_long <= InvalidOid) {
        !          3119:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
        !          3120:                        RETURN_FALSE;
        !          3121:                }
        !          3122:                oid = (Oid)oid_long;
        !          3123:                id = PGG(default_link);
        !          3124:                CHECK_DEFAULT_LINK(id);
        !          3125:        }
        !          3126:        else {
        !          3127:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Requires 1 or 2 arguments");
        !          3128:                RETURN_FALSE;
        !          3129:        }
        !          3130:        if (pgsql_link == NULL && id == -1) {
        !          3131:                RETURN_FALSE;
        !          3132:        }       
        !          3133: 
        !          3134:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          3135:        
        !          3136:        /* r/w/+ is little bit more PHP-like than INV_READ/INV_WRITE and a lot of
        !          3137:           faster to type. Unfortunately, doesn't behave the same way as fopen()...
        !          3138:           (Jouni)
        !          3139:        */
        !          3140: 
        !          3141:        if (strchr(mode_string, 'r') == mode_string) {
        !          3142:                pgsql_mode |= INV_READ;
        !          3143:                if (strchr(mode_string, '+') == mode_string+1) {
        !          3144:                        pgsql_mode |= INV_WRITE;
        !          3145:                }
        !          3146:        }
        !          3147:        if (strchr(mode_string, 'w') == mode_string) {
        !          3148:                pgsql_mode |= INV_WRITE;
        !          3149:                create = 1;
        !          3150:                if (strchr(mode_string, '+') == mode_string+1) {
        !          3151:                        pgsql_mode |= INV_READ;
        !          3152:                }
        !          3153:        }
        !          3154: 
        !          3155:        pgsql_lofp = (pgLofp *) emalloc(sizeof(pgLofp));
        !          3156: 
        !          3157:        if ((pgsql_lofd = lo_open(pgsql, oid, pgsql_mode)) == -1) {
        !          3158:                if (create) {
        !          3159:                        if ((oid = lo_creat(pgsql, INV_READ|INV_WRITE)) == 0) {
        !          3160:                                efree(pgsql_lofp);
        !          3161:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create PostgreSQL large object");
        !          3162:                                RETURN_FALSE;
        !          3163:                        } else {
        !          3164:                                if ((pgsql_lofd = lo_open(pgsql, oid, pgsql_mode)) == -1) {
        !          3165:                                        if (lo_unlink(pgsql, oid) == -1) {
        !          3166:                                                efree(pgsql_lofp);
        !          3167:                                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Something is really messed up! Your database is badly corrupted in a way NOT related to PHP");
        !          3168:                                                RETURN_FALSE;
        !          3169:                                        }
        !          3170:                                        efree(pgsql_lofp);
        !          3171:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open PostgreSQL large object");
        !          3172:                                        RETURN_FALSE;
        !          3173:                                } else {
        !          3174:                                        pgsql_lofp->conn = pgsql;
        !          3175:                                        pgsql_lofp->lofd = pgsql_lofd;
        !          3176:                                        Z_LVAL_P(return_value) = zend_list_insert(pgsql_lofp, le_lofp);
        !          3177:                                        Z_TYPE_P(return_value) = IS_LONG;
        !          3178:                                }
        !          3179:                        }
        !          3180:                } else {
        !          3181:                        efree(pgsql_lofp);
        !          3182:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open PostgreSQL large object");
        !          3183:                        RETURN_FALSE;
        !          3184:                }
        !          3185:        } else {
        !          3186:                pgsql_lofp->conn = pgsql;
        !          3187:                pgsql_lofp->lofd = pgsql_lofd;
        !          3188:                ZEND_REGISTER_RESOURCE(return_value, pgsql_lofp, le_lofp);
        !          3189:        }
        !          3190: }
        !          3191: /* }}} */
        !          3192: 
        !          3193: /* {{{ proto bool pg_lo_close(resource large_object)
        !          3194:    Close a large object */
        !          3195: PHP_FUNCTION(pg_lo_close)
        !          3196: {
        !          3197:        zval *pgsql_lofp;
        !          3198:        pgLofp *pgsql;
        !          3199: 
        !          3200:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pgsql_lofp) == FAILURE) {
        !          3201:                return;
        !          3202:        }
        !          3203: 
        !          3204:        ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_lofp, -1, "PostgreSQL large object", le_lofp);
        !          3205:        
        !          3206:        if (lo_close((PGconn *)pgsql->conn, pgsql->lofd) < 0) {
        !          3207:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to close PostgreSQL large object descriptor %d", pgsql->lofd);
        !          3208:                RETVAL_FALSE;
        !          3209:        } else {
        !          3210:                RETVAL_TRUE;
        !          3211:        }
        !          3212: 
        !          3213:        zend_list_delete(Z_RESVAL_P(pgsql_lofp));
        !          3214:        return;
        !          3215: }
        !          3216: /* }}} */
        !          3217: 
        !          3218: #define PGSQL_LO_READ_BUF_SIZE  8192
        !          3219: 
        !          3220: /* {{{ proto string pg_lo_read(resource large_object [, int len])
        !          3221:    Read a large object */
        !          3222: PHP_FUNCTION(pg_lo_read)
        !          3223: {
        !          3224:        zval *pgsql_id;
        !          3225:        long len;
        !          3226:        int buf_len = PGSQL_LO_READ_BUF_SIZE, nbytes, argc = ZEND_NUM_ARGS();
        !          3227:        char *buf;
        !          3228:        pgLofp *pgsql;
        !          3229: 
        !          3230:        if (zend_parse_parameters(argc TSRMLS_CC, "r|l", &pgsql_id, &len) == FAILURE) {
        !          3231:                return;
        !          3232:        }
        !          3233: 
        !          3234:        ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_id, -1, "PostgreSQL large object", le_lofp);
        !          3235: 
        !          3236:        if (argc > 1) {
        !          3237:                buf_len = len;
        !          3238:        }
        !          3239:        
        !          3240:        buf = (char *) safe_emalloc(sizeof(char), (buf_len+1), 0);
        !          3241:        if ((nbytes = lo_read((PGconn *)pgsql->conn, pgsql->lofd, buf, buf_len))<0) {
        !          3242:                efree(buf);
        !          3243:                RETURN_FALSE;
        !          3244:        }
        !          3245: 
        !          3246:        buf[nbytes] = '\0';
        !          3247:        RETURN_STRINGL(buf, nbytes, 0);
        !          3248: }
        !          3249: /* }}} */
        !          3250: 
        !          3251: /* {{{ proto int pg_lo_write(resource large_object, string buf [, int len])
        !          3252:    Write a large object */
        !          3253: PHP_FUNCTION(pg_lo_write)
        !          3254: {
        !          3255:        zval *pgsql_id;
        !          3256:        char *str;
        !          3257:        long z_len;
        !          3258:        int str_len, nbytes;
        !          3259:        int len;
        !          3260:        pgLofp *pgsql;
        !          3261:        int argc = ZEND_NUM_ARGS();
        !          3262: 
        !          3263:        if (zend_parse_parameters(argc TSRMLS_CC, "rs|l", &pgsql_id, &str, &str_len, &z_len) == FAILURE) {
        !          3264:                return;
        !          3265:        }
        !          3266: 
        !          3267:        if (argc > 2) {
        !          3268:                if (z_len > str_len) {
        !          3269:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot write more than buffer size %d. Tried to write %ld", str_len, z_len);
        !          3270:                        RETURN_FALSE;
        !          3271:                }
        !          3272:                if (z_len < 0) {
        !          3273:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Buffer size must be larger than 0, but %ld was specified", z_len);
        !          3274:                        RETURN_FALSE;
        !          3275:                }
        !          3276:                len = z_len;
        !          3277:        }
        !          3278:        else {
        !          3279:                len = str_len;
        !          3280:        }
        !          3281: 
        !          3282:        ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_id, -1, "PostgreSQL large object", le_lofp);
        !          3283: 
        !          3284:        if ((nbytes = lo_write((PGconn *)pgsql->conn, pgsql->lofd, str, len)) == -1) {
        !          3285:                RETURN_FALSE;
        !          3286:        }
        !          3287: 
        !          3288:        RETURN_LONG(nbytes);
        !          3289: }
        !          3290: /* }}} */
        !          3291: 
        !          3292: /* {{{ proto int pg_lo_read_all(resource large_object)
        !          3293:    Read a large object and send straight to browser */
        !          3294: PHP_FUNCTION(pg_lo_read_all)
        !          3295: {
        !          3296:        zval *pgsql_id;
        !          3297:        int tbytes;
        !          3298:        volatile int nbytes;
        !          3299:        char buf[PGSQL_LO_READ_BUF_SIZE];
        !          3300:        pgLofp *pgsql;
        !          3301:        
        !          3302:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pgsql_id) == FAILURE) {
        !          3303:                return;
        !          3304:        }
        !          3305: 
        !          3306:        ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_id, -1, "PostgreSQL large object", le_lofp);
        !          3307: 
        !          3308:        tbytes = 0;
        !          3309:        while ((nbytes = lo_read((PGconn *)pgsql->conn, pgsql->lofd, buf, PGSQL_LO_READ_BUF_SIZE))>0) {
        !          3310:                PHPWRITE(buf, nbytes);
        !          3311:                tbytes += nbytes;
        !          3312:        }
        !          3313:        RETURN_LONG(tbytes);
        !          3314: }
        !          3315: /* }}} */
        !          3316: 
        !          3317: /* {{{ proto int pg_lo_import([resource connection, ] string filename [, mixed oid])
        !          3318:    Import large object direct from filesystem */
        !          3319: PHP_FUNCTION(pg_lo_import)
        !          3320: {
        !          3321:        zval *pgsql_link = NULL, *oid = NULL;
        !          3322:        char *file_in;
        !          3323:        int id = -1, name_len;
        !          3324:        int argc = ZEND_NUM_ARGS();
        !          3325:        PGconn *pgsql;
        !          3326:        Oid returned_oid;
        !          3327: 
        !          3328:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
        !          3329:                                                                 "rs|z", &pgsql_link, &file_in, &name_len, &oid) == SUCCESS) {
        !          3330:                ;
        !          3331:        }
        !          3332:        else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
        !          3333:                                                                          "s|z", &file_in, &name_len, &oid) == SUCCESS) {
        !          3334:                id = PGG(default_link);
        !          3335:                CHECK_DEFAULT_LINK(id);
        !          3336:        }
        !          3337:        /* old calling convention, deprecated since PHP 4.2 */
        !          3338:        else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
        !          3339:                                                                          "sr", &file_in, &name_len, &pgsql_link ) == SUCCESS) {
        !          3340:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Old API is used");
        !          3341:        }
        !          3342:        else {
        !          3343:                WRONG_PARAM_COUNT;
        !          3344:        }
        !          3345: 
        !          3346:        if (strlen(file_in) != name_len) {
        !          3347:                RETURN_FALSE;
        !          3348:        }
        !          3349: 
        !          3350:        if (PG(safe_mode) &&(!php_checkuid(file_in, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
        !          3351:                RETURN_FALSE;
        !          3352:        }
        !          3353:        
        !          3354:        if (php_check_open_basedir(file_in TSRMLS_CC)) {
        !          3355:                RETURN_FALSE;
        !          3356:        }
        !          3357: 
        !          3358:        if (pgsql_link == NULL && id == -1) {
        !          3359:                RETURN_FALSE;
        !          3360:        }       
        !          3361: 
        !          3362:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          3363: 
        !          3364:        if (oid) {
        !          3365: #ifndef HAVE_PG_LO_IMPORT_WITH_OID
        !          3366:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "OID value passing not supported");
        !          3367: #else
        !          3368:                Oid wanted_oid;
        !          3369:                switch (Z_TYPE_P(oid)) {
        !          3370:                case IS_STRING:
        !          3371:                        {       
        !          3372:                                char *end_ptr;
        !          3373:                                wanted_oid = (Oid)strtoul(Z_STRVAL_P(oid), &end_ptr, 10);
        !          3374:                                if ((Z_STRVAL_P(oid)+Z_STRLEN_P(oid)) != end_ptr) {
        !          3375:                                /* wrong integer format */
        !          3376:                                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
        !          3377:                                RETURN_FALSE;
        !          3378:                                }
        !          3379:                        }
        !          3380:                        break;
        !          3381:                case IS_LONG:
        !          3382:                        if (Z_LVAL_P(oid) < (long)InvalidOid) {
        !          3383:                                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
        !          3384:                                RETURN_FALSE;
        !          3385:                        }
        !          3386:                        wanted_oid = (Oid)Z_LVAL_P(oid);
        !          3387:                        break;
        !          3388:                default:
        !          3389:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
        !          3390:                        RETURN_FALSE;
        !          3391:         }
        !          3392: 
        !          3393:        returned_oid = lo_import_with_oid(pgsql, file_in, wanted_oid);
        !          3394: 
        !          3395:           if (returned_oid == InvalidOid) {
        !          3396:                   RETURN_FALSE;
        !          3397:           }
        !          3398: 
        !          3399:           PGSQL_RETURN_OID(returned_oid);
        !          3400: #endif
        !          3401:        }
        !          3402: 
        !          3403:        returned_oid = lo_import(pgsql, file_in);
        !          3404: 
        !          3405:        if (returned_oid == InvalidOid) {
        !          3406:                RETURN_FALSE;
        !          3407:        }
        !          3408:        PGSQL_RETURN_OID(returned_oid);
        !          3409: }
        !          3410: /* }}} */
        !          3411: 
        !          3412: /* {{{ proto bool pg_lo_export([resource connection, ] int objoid, string filename)
        !          3413:    Export large object direct to filesystem */
        !          3414: PHP_FUNCTION(pg_lo_export)
        !          3415: {
        !          3416:        zval *pgsql_link = NULL;
        !          3417:        char *file_out, *oid_string, *end_ptr;
        !          3418:        int oid_strlen;
        !          3419:        int id = -1, name_len;
        !          3420:        long oid_long;
        !          3421:        Oid oid;
        !          3422:        PGconn *pgsql;
        !          3423:        int argc = ZEND_NUM_ARGS();
        !          3424: 
        !          3425:        /* allow string to handle large OID value correctly */
        !          3426:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
        !          3427:                                                                 "rls", &pgsql_link, &oid_long, &file_out, &name_len) == SUCCESS) {
        !          3428:                if (oid_long <= InvalidOid) {
        !          3429:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
        !          3430:                        RETURN_FALSE;
        !          3431:                }
        !          3432:                oid = (Oid)oid_long;
        !          3433:        }
        !          3434:        else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
        !          3435:                                                                 "rss", &pgsql_link, &oid_string, &oid_strlen, &file_out, &name_len) == SUCCESS) {
        !          3436:                oid = (Oid)strtoul(oid_string, &end_ptr, 10);
        !          3437:                if ((oid_string+oid_strlen) != end_ptr) {
        !          3438:                        /* wrong integer format */
        !          3439:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
        !          3440:                        RETURN_FALSE;
        !          3441:                }
        !          3442:        }
        !          3443:        else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
        !          3444:                                                                          "ls",  &oid_long, &file_out, &name_len) == SUCCESS) {
        !          3445:                if (oid_long <= InvalidOid) {
        !          3446:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
        !          3447:                        RETURN_FALSE;
        !          3448:                }
        !          3449:                oid = (Oid)oid_long;
        !          3450:                id = PGG(default_link);
        !          3451:                CHECK_DEFAULT_LINK(id);
        !          3452:        }
        !          3453:        else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
        !          3454:                                                                 "ss", &oid_string, &oid_strlen, &file_out, &name_len) == SUCCESS) {
        !          3455:                oid = (Oid)strtoul(oid_string, &end_ptr, 10);
        !          3456:                if ((oid_string+oid_strlen) != end_ptr) {
        !          3457:                        /* wrong integer format */
        !          3458:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
        !          3459:                        RETURN_FALSE;
        !          3460:                }
        !          3461:                id = PGG(default_link);
        !          3462:                CHECK_DEFAULT_LINK(id);
        !          3463:        }
        !          3464:        else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
        !          3465:                                                                 "ssr", &oid_string, &oid_strlen, &file_out, &name_len, &pgsql_link) == SUCCESS) {
        !          3466:                oid = (Oid)strtoul(oid_string, &end_ptr, 10);
        !          3467:                if ((oid_string+oid_strlen) != end_ptr) {
        !          3468:                        /* wrong integer format */
        !          3469:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
        !          3470:                        RETURN_FALSE;
        !          3471:                }
        !          3472:        }
        !          3473:        else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
        !          3474:                                                                          "lsr", &oid_long, &file_out, &name_len, &pgsql_link) == SUCCESS) {
        !          3475:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Old API is used");
        !          3476:                if (oid_long <= InvalidOid) {
        !          3477:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
        !          3478:                        RETURN_FALSE;
        !          3479:                }
        !          3480:                oid = (Oid)oid_long;
        !          3481:        }
        !          3482:        else {
        !          3483:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Requires 2 or 3 arguments");
        !          3484:                RETURN_FALSE;
        !          3485:        }
        !          3486: 
        !          3487:        if (strlen(file_out) != name_len) {
        !          3488:                RETURN_FALSE;
        !          3489:        }
        !          3490: 
        !          3491:        if (PG(safe_mode) &&(!php_checkuid(file_out, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
        !          3492:                RETURN_FALSE;
        !          3493:        }
        !          3494:        
        !          3495:        if (php_check_open_basedir(file_out TSRMLS_CC)) {
        !          3496:                RETURN_FALSE;
        !          3497:        }
        !          3498: 
        !          3499:        if (pgsql_link == NULL && id == -1) {
        !          3500:                RETURN_FALSE;
        !          3501:        }       
        !          3502: 
        !          3503:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          3504: 
        !          3505:        if (lo_export(pgsql, oid, file_out)) {
        !          3506:                RETURN_TRUE;
        !          3507:        } 
        !          3508:        RETURN_FALSE;
        !          3509: }
        !          3510: /* }}} */
        !          3511: 
        !          3512: /* {{{ proto bool pg_lo_seek(resource large_object, int offset [, int whence])
        !          3513:    Seeks position of large object */
        !          3514: PHP_FUNCTION(pg_lo_seek)
        !          3515: {
        !          3516:        zval *pgsql_id = NULL;
        !          3517:        long offset = 0, whence = SEEK_CUR;
        !          3518:        pgLofp *pgsql;
        !          3519:        int argc = ZEND_NUM_ARGS();
        !          3520: 
        !          3521:        if (zend_parse_parameters(argc TSRMLS_CC, "rl|l", &pgsql_id, &offset, &whence) == FAILURE) {
        !          3522:                return;
        !          3523:        }
        !          3524:        if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) {
        !          3525:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid whence parameter");
        !          3526:                return;
        !          3527:        }
        !          3528: 
        !          3529:        ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_id, -1, "PostgreSQL large object", le_lofp);
        !          3530: 
        !          3531:        if (lo_lseek((PGconn *)pgsql->conn, pgsql->lofd, offset, whence) > -1) {
        !          3532:                RETURN_TRUE;
        !          3533:        } else {
        !          3534:                RETURN_FALSE;
        !          3535:        }
        !          3536: }
        !          3537: /* }}} */
        !          3538: 
        !          3539: /* {{{ proto int pg_lo_tell(resource large_object)
        !          3540:    Returns current position of large object */
        !          3541: PHP_FUNCTION(pg_lo_tell)
        !          3542: {
        !          3543:        zval *pgsql_id = NULL;
        !          3544:        int offset = 0;
        !          3545:        pgLofp *pgsql;
        !          3546:        int argc = ZEND_NUM_ARGS();
        !          3547: 
        !          3548:        if (zend_parse_parameters(argc TSRMLS_CC, "r", &pgsql_id) == FAILURE) {
        !          3549:                return;
        !          3550:        }
        !          3551: 
        !          3552:        ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_id, -1, "PostgreSQL large object", le_lofp);
        !          3553: 
        !          3554:        offset = lo_tell((PGconn *)pgsql->conn, pgsql->lofd);
        !          3555:        RETURN_LONG(offset);
        !          3556: }
        !          3557: /* }}} */
        !          3558: 
        !          3559: #if HAVE_PQSETERRORVERBOSITY
        !          3560: /* {{{ proto int pg_set_error_verbosity([resource connection,] int verbosity)
        !          3561:    Set error verbosity */
        !          3562: PHP_FUNCTION(pg_set_error_verbosity)
        !          3563: {
        !          3564:        zval *pgsql_link = NULL;
        !          3565:        long verbosity;
        !          3566:        int id = -1, argc = ZEND_NUM_ARGS();
        !          3567:        PGconn *pgsql;
        !          3568: 
        !          3569:        if (argc == 1) {
        !          3570:                if (zend_parse_parameters(argc TSRMLS_CC, "l", &verbosity) == FAILURE) {
        !          3571:                        return;
        !          3572:                }
        !          3573:                id = PGG(default_link);
        !          3574:                CHECK_DEFAULT_LINK(id);
        !          3575:        } else {
        !          3576:                if (zend_parse_parameters(argc TSRMLS_CC, "rl", &pgsql_link, &verbosity) == FAILURE) {
        !          3577:                        return;
        !          3578:                }
        !          3579:        }
        !          3580: 
        !          3581:        if (pgsql_link == NULL && id == -1) {
        !          3582:                RETURN_FALSE;
        !          3583:        }       
        !          3584: 
        !          3585:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          3586: 
        !          3587:        if (verbosity & (PQERRORS_TERSE|PQERRORS_DEFAULT|PQERRORS_VERBOSE)) {
        !          3588:                Z_LVAL_P(return_value) = PQsetErrorVerbosity(pgsql, verbosity);
        !          3589:                Z_TYPE_P(return_value) = IS_LONG;
        !          3590:        } else {
        !          3591:                RETURN_FALSE;
        !          3592:        }
        !          3593: }
        !          3594: /* }}} */
        !          3595: #endif
        !          3596: 
        !          3597: #ifdef HAVE_PQCLIENTENCODING
        !          3598: /* {{{ proto int pg_set_client_encoding([resource connection,] string encoding)
        !          3599:    Set client encoding */
        !          3600: PHP_FUNCTION(pg_set_client_encoding)
        !          3601: {
        !          3602:        char *encoding;
        !          3603:        int encoding_len;
        !          3604:        zval *pgsql_link = NULL;
        !          3605:        int id = -1, argc = ZEND_NUM_ARGS();
        !          3606:        PGconn *pgsql;
        !          3607: 
        !          3608:        if (argc == 1) {
        !          3609:                if (zend_parse_parameters(argc TSRMLS_CC, "s", &encoding, &encoding_len) == FAILURE) {
        !          3610:                        return;
        !          3611:                }
        !          3612:                id = PGG(default_link);
        !          3613:                CHECK_DEFAULT_LINK(id);
        !          3614:        } else {
        !          3615:                if (zend_parse_parameters(argc TSRMLS_CC, "rs", &pgsql_link, &encoding, &encoding_len) == FAILURE) {
        !          3616:                        return;
        !          3617:                }
        !          3618:        }
        !          3619: 
        !          3620:        if (pgsql_link == NULL && id == -1) {
        !          3621:                RETURN_FALSE;
        !          3622:        }       
        !          3623: 
        !          3624:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          3625: 
        !          3626:        Z_LVAL_P(return_value) = PQsetClientEncoding(pgsql, encoding);
        !          3627:        Z_TYPE_P(return_value) = IS_LONG;
        !          3628: }
        !          3629: /* }}} */
        !          3630: 
        !          3631: /* {{{ proto string pg_client_encoding([resource connection])
        !          3632:    Get the current client encoding */
        !          3633: PHP_FUNCTION(pg_client_encoding)
        !          3634: {
        !          3635:        zval *pgsql_link = NULL;
        !          3636:        int id = -1, argc = ZEND_NUM_ARGS();
        !          3637:        PGconn *pgsql;
        !          3638: 
        !          3639:        if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) {
        !          3640:                return;
        !          3641:        }
        !          3642:        
        !          3643:        if (argc == 0) {
        !          3644:                id = PGG(default_link);
        !          3645:                CHECK_DEFAULT_LINK(id);
        !          3646:        }
        !          3647: 
        !          3648:        if (pgsql_link == NULL && id == -1) {
        !          3649:                RETURN_FALSE;
        !          3650:        }       
        !          3651: 
        !          3652:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          3653: 
        !          3654:        /* Just do the same as found in PostgreSQL sources... */
        !          3655: 
        !          3656: #ifndef HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT
        !          3657: #define pg_encoding_to_char(x) "SQL_ASCII"
        !          3658: #endif
        !          3659: 
        !          3660:        Z_STRVAL_P(return_value) = (char *) pg_encoding_to_char(PQclientEncoding(pgsql));
        !          3661:        Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
        !          3662:        Z_STRVAL_P(return_value) = (char *) estrdup(Z_STRVAL_P(return_value));
        !          3663:        Z_TYPE_P(return_value) = IS_STRING;
        !          3664: }
        !          3665: /* }}} */
        !          3666: #endif
        !          3667: 
        !          3668: #if !HAVE_PQGETCOPYDATA
        !          3669: #define        COPYBUFSIZ      8192
        !          3670: #endif
        !          3671: 
        !          3672: /* {{{ proto bool pg_end_copy([resource connection])
        !          3673:    Sync with backend. Completes the Copy command */
        !          3674: PHP_FUNCTION(pg_end_copy)
        !          3675: {
        !          3676:        zval *pgsql_link = NULL;
        !          3677:        int id = -1, argc = ZEND_NUM_ARGS();
        !          3678:        PGconn *pgsql;
        !          3679:        int result = 0;
        !          3680: 
        !          3681:        if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) {
        !          3682:                return;
        !          3683:        }
        !          3684:        
        !          3685:        if (argc == 0) {
        !          3686:                id = PGG(default_link);
        !          3687:                CHECK_DEFAULT_LINK(id);
        !          3688:        }
        !          3689: 
        !          3690:        if (pgsql_link == NULL && id == -1) {
        !          3691:                RETURN_FALSE;
        !          3692:        }       
        !          3693: 
        !          3694:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          3695: 
        !          3696:        result = PQendcopy(pgsql);
        !          3697: 
        !          3698:        if (result!=0) {
        !          3699:                PHP_PQ_ERROR("Query failed: %s", pgsql);
        !          3700:                RETURN_FALSE;
        !          3701:        }
        !          3702:        RETURN_TRUE;
        !          3703: }
        !          3704: /* }}} */
        !          3705: 
        !          3706: 
        !          3707: /* {{{ proto bool pg_put_line([resource connection,] string query)
        !          3708:    Send null-terminated string to backend server*/
        !          3709: PHP_FUNCTION(pg_put_line)
        !          3710: {
        !          3711:        char *query;
        !          3712:        zval *pgsql_link = NULL;
        !          3713:        int query_len, id = -1;
        !          3714:        PGconn *pgsql;
        !          3715:        int result = 0, argc = ZEND_NUM_ARGS();
        !          3716: 
        !          3717:        if (argc == 1) {
        !          3718:                if (zend_parse_parameters(argc TSRMLS_CC, "s", &query, &query_len) == FAILURE) {
        !          3719:                        return;
        !          3720:                }
        !          3721:                id = PGG(default_link);
        !          3722:                CHECK_DEFAULT_LINK(id);
        !          3723:        } else {
        !          3724:                if (zend_parse_parameters(argc TSRMLS_CC, "rs", &pgsql_link, &query, &query_len) == FAILURE) {
        !          3725:                        return;
        !          3726:                }
        !          3727:        }
        !          3728: 
        !          3729:        if (pgsql_link == NULL && id == -1) {
        !          3730:                RETURN_FALSE;
        !          3731:        }       
        !          3732: 
        !          3733:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          3734: 
        !          3735:        result = PQputline(pgsql, query);
        !          3736:        if (result==EOF) {
        !          3737:                PHP_PQ_ERROR("Query failed: %s", pgsql);
        !          3738:                RETURN_FALSE;
        !          3739:        }
        !          3740:        RETURN_TRUE;
        !          3741: }
        !          3742: /* }}} */
        !          3743: 
        !          3744: /* {{{ proto array pg_copy_to(resource connection, string table_name [, string delimiter [, string null_as]])
        !          3745:    Copy table to array */
        !          3746: PHP_FUNCTION(pg_copy_to)
        !          3747: {
        !          3748:        zval *pgsql_link;
        !          3749:        char *table_name, *pg_delim = NULL, *pg_null_as = NULL;
        !          3750:        int table_name_len, pg_delim_len, pg_null_as_len, free_pg_null = 0;
        !          3751:        char *query;
        !          3752:        int id = -1;
        !          3753:        PGconn *pgsql;
        !          3754:        PGresult *pgsql_result;
        !          3755:        ExecStatusType status;
        !          3756:        int copydone = 0;
        !          3757: #if !HAVE_PQGETCOPYDATA
        !          3758:        char copybuf[COPYBUFSIZ];
        !          3759: #endif
        !          3760:        char *csv = (char *)NULL;
        !          3761:        int ret;
        !          3762:        int argc = ZEND_NUM_ARGS();
        !          3763: 
        !          3764:        if (zend_parse_parameters(argc TSRMLS_CC, "rs|ss",
        !          3765:                                                          &pgsql_link, &table_name, &table_name_len,
        !          3766:                                                          &pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len) == FAILURE) {
        !          3767:                return;
        !          3768:        }
        !          3769:        if (!pg_delim) {
        !          3770:                pg_delim = "\t";
        !          3771:        }
        !          3772: 
        !          3773:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          3774: 
        !          3775:        if (!pg_null_as) {
        !          3776:                pg_null_as = safe_estrdup("\\\\N");
        !          3777:                free_pg_null = 1;
        !          3778:        }
        !          3779: 
        !          3780:        spprintf(&query, 0, "COPY %s TO STDOUT DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, *pg_delim, pg_null_as);
        !          3781: 
        !          3782:        while ((pgsql_result = PQgetResult(pgsql))) {
        !          3783:                PQclear(pgsql_result);
        !          3784:        }
        !          3785:        pgsql_result = PQexec(pgsql, query);
        !          3786:        if (free_pg_null) {
        !          3787:                efree(pg_null_as);
        !          3788:        }
        !          3789:        efree(query);
        !          3790: 
        !          3791:        if (pgsql_result) {
        !          3792:                status = PQresultStatus(pgsql_result);
        !          3793:        } else {
        !          3794:                status = (ExecStatusType) PQstatus(pgsql);
        !          3795:        }
        !          3796: 
        !          3797:        switch (status) {
        !          3798:                case PGRES_COPY_OUT:
        !          3799:                        if (pgsql_result) {
        !          3800:                                PQclear(pgsql_result);
        !          3801:                                array_init(return_value);
        !          3802: #if HAVE_PQGETCOPYDATA
        !          3803:                                while (!copydone)
        !          3804:                                {
        !          3805:                                        ret = PQgetCopyData(pgsql, &csv, 0);
        !          3806:                                        switch (ret) {
        !          3807:                                                case -1:
        !          3808:                                                        copydone = 1;
        !          3809:                                                        break;
        !          3810:                                                case 0:
        !          3811:                                                case -2:
        !          3812:                                                        PHP_PQ_ERROR("getline failed: %s", pgsql);
        !          3813:                                                        RETURN_FALSE;
        !          3814:                                                        break;
        !          3815:                                                default:
        !          3816:                                                        add_next_index_string(return_value, csv, 1);
        !          3817:                                                        PQfreemem(csv);
        !          3818:                                                        break;
        !          3819:                                        }
        !          3820:                                }
        !          3821: #else
        !          3822:                                while (!copydone)
        !          3823:                                {
        !          3824:                                        if ((ret = PQgetline(pgsql, copybuf, COPYBUFSIZ))) {
        !          3825:                                                PHP_PQ_ERROR("getline failed: %s", pgsql);
        !          3826:                                                RETURN_FALSE;
        !          3827:                                        }
        !          3828:                        
        !          3829:                                        if (copybuf[0] == '\\' &&
        !          3830:                                                copybuf[1] == '.' &&
        !          3831:                                                copybuf[2] == '\0')
        !          3832:                                        {
        !          3833:                                                copydone = 1;
        !          3834:                                        }
        !          3835:                                        else
        !          3836:                                        {
        !          3837:                                                if (csv == (char *)NULL) {
        !          3838:                                                        csv = estrdup(copybuf);
        !          3839:                                                } else {
        !          3840:                                                        csv = (char *)erealloc(csv, strlen(csv) + sizeof(char)*(COPYBUFSIZ+1));
        !          3841:                                                        strcat(csv, copybuf);
        !          3842:                                                }
        !          3843:                                                        
        !          3844:                                                switch (ret)
        !          3845:                                                {
        !          3846:                                                        case EOF:
        !          3847:                                                                copydone = 1;
        !          3848:                                                        case 0:
        !          3849:                                                                add_next_index_string(return_value, csv, 1);
        !          3850:                                                                efree(csv);
        !          3851:                                                                csv = (char *)NULL;
        !          3852:                                                                break;
        !          3853:                                                        case 1:
        !          3854:                                                                break;
        !          3855:                                                }
        !          3856:                                        }
        !          3857:                                }
        !          3858:                                if (PQendcopy(pgsql)) {
        !          3859:                                        PHP_PQ_ERROR("endcopy failed: %s", pgsql);
        !          3860:                                        RETURN_FALSE;
        !          3861:                                }
        !          3862: #endif
        !          3863:                                while ((pgsql_result = PQgetResult(pgsql))) {
        !          3864:                                        PQclear(pgsql_result);
        !          3865:                                }
        !          3866:                        } else {
        !          3867:                                PQclear(pgsql_result);
        !          3868:                                RETURN_FALSE;
        !          3869:                        }
        !          3870:                        break;
        !          3871:                default:
        !          3872:                        PQclear(pgsql_result);
        !          3873:                        PHP_PQ_ERROR("Copy command failed: %s", pgsql);
        !          3874:                        RETURN_FALSE;
        !          3875:                        break;
        !          3876:        }
        !          3877: }
        !          3878: /* }}} */
        !          3879: 
        !          3880: /* {{{ proto bool pg_copy_from(resource connection, string table_name , array rows [, string delimiter [, string null_as]])
        !          3881:    Copy table from array */
        !          3882: PHP_FUNCTION(pg_copy_from)
        !          3883: {
        !          3884:        zval *pgsql_link = NULL, *pg_rows;
        !          3885:        zval **tmp;
        !          3886:        char *table_name, *pg_delim = NULL, *pg_null_as = NULL;
        !          3887:        int  table_name_len, pg_delim_len, pg_null_as_len;
        !          3888:        int  pg_null_as_free = 0;
        !          3889:        char *query;
        !          3890:        HashPosition pos;
        !          3891:        int id = -1;
        !          3892:        PGconn *pgsql;
        !          3893:        PGresult *pgsql_result;
        !          3894:        ExecStatusType status;
        !          3895:        int argc = ZEND_NUM_ARGS();
        !          3896: 
        !          3897:        if (zend_parse_parameters(argc TSRMLS_CC, "rsa|ss",
        !          3898:                                                          &pgsql_link, &table_name, &table_name_len, &pg_rows,
        !          3899:                                                          &pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len) == FAILURE) {
        !          3900:                return;
        !          3901:        }
        !          3902:        if (!pg_delim) {
        !          3903:                pg_delim = "\t";
        !          3904:        }
        !          3905:        if (!pg_null_as) {
        !          3906:                pg_null_as = safe_estrdup("\\\\N");
        !          3907:                pg_null_as_free = 1;
        !          3908:        }
        !          3909: 
        !          3910:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          3911: 
        !          3912:        spprintf(&query, 0, "COPY %s FROM STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, *pg_delim, pg_null_as);
        !          3913:        while ((pgsql_result = PQgetResult(pgsql))) {
        !          3914:                PQclear(pgsql_result);
        !          3915:        }
        !          3916:        pgsql_result = PQexec(pgsql, query);
        !          3917: 
        !          3918:        if (pg_null_as_free) {
        !          3919:                efree(pg_null_as);
        !          3920:        }
        !          3921:        efree(query);
        !          3922: 
        !          3923:        if (pgsql_result) {
        !          3924:                status = PQresultStatus(pgsql_result);
        !          3925:        } else {
        !          3926:                status = (ExecStatusType) PQstatus(pgsql);
        !          3927:        }
        !          3928: 
        !          3929:        switch (status) {
        !          3930:                case PGRES_COPY_IN:
        !          3931:                        if (pgsql_result) {
        !          3932:                                int command_failed = 0;
        !          3933:                                PQclear(pgsql_result);
        !          3934:                                zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(pg_rows), &pos);
        !          3935: #if HAVE_PQPUTCOPYDATA
        !          3936:                                while (zend_hash_get_current_data_ex(Z_ARRVAL_P(pg_rows), (void **) &tmp, &pos) == SUCCESS) {
        !          3937:                                        convert_to_string_ex(tmp);
        !          3938:                                        query = (char *)emalloc(Z_STRLEN_PP(tmp) + 2);
        !          3939:                                        strlcpy(query, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp) + 2);
        !          3940:                                        if(Z_STRLEN_PP(tmp) > 0 && *(query + Z_STRLEN_PP(tmp) - 1) != '\n') {
        !          3941:                                                strlcat(query, "\n", Z_STRLEN_PP(tmp) + 2);
        !          3942:                                        }
        !          3943:                                        if (PQputCopyData(pgsql, query, strlen(query)) != 1) {
        !          3944:                                                efree(query);
        !          3945:                                                PHP_PQ_ERROR("copy failed: %s", pgsql);
        !          3946:                                                RETURN_FALSE;
        !          3947:                                        }
        !          3948:                                        efree(query);
        !          3949:                                        zend_hash_move_forward_ex(Z_ARRVAL_P(pg_rows), &pos);
        !          3950:                                }
        !          3951:                                if (PQputCopyEnd(pgsql, NULL) != 1) {
        !          3952:                                        PHP_PQ_ERROR("putcopyend failed: %s", pgsql);
        !          3953:                                        RETURN_FALSE;
        !          3954:                                }
        !          3955: #else
        !          3956:                                while (zend_hash_get_current_data_ex(Z_ARRVAL_P(pg_rows), (void **) &tmp, &pos) == SUCCESS) {
        !          3957:                                        convert_to_string_ex(tmp);
        !          3958:                                        query = (char *)emalloc(Z_STRLEN_PP(tmp) + 2);
        !          3959:                                        strlcpy(query, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp) + 2);
        !          3960:                                        if(Z_STRLEN_PP(tmp) > 0 && *(query + Z_STRLEN_PP(tmp) - 1) != '\n') {
        !          3961:                                                strlcat(query, "\n", Z_STRLEN_PP(tmp) + 2);
        !          3962:                                        }
        !          3963:                                        if (PQputline(pgsql, query)==EOF) {
        !          3964:                                                efree(query);
        !          3965:                                                PHP_PQ_ERROR("copy failed: %s", pgsql);
        !          3966:                                                RETURN_FALSE;
        !          3967:                                        }
        !          3968:                                        efree(query);
        !          3969:                                        zend_hash_move_forward_ex(Z_ARRVAL_P(pg_rows), &pos);
        !          3970:                                }
        !          3971:                                if (PQputline(pgsql, "\\.\n") == EOF) {
        !          3972:                                        PHP_PQ_ERROR("putline failed: %s", pgsql);
        !          3973:                                        RETURN_FALSE;
        !          3974:                                }
        !          3975:                                if (PQendcopy(pgsql)) {
        !          3976:                                        PHP_PQ_ERROR("endcopy failed: %s", pgsql);
        !          3977:                                        RETURN_FALSE;
        !          3978:                                }
        !          3979: #endif
        !          3980:                                while ((pgsql_result = PQgetResult(pgsql))) {
        !          3981:                                        if (PGRES_COMMAND_OK != PQresultStatus(pgsql_result)) {
        !          3982:                                                PHP_PQ_ERROR("Copy command failed: %s", pgsql);
        !          3983:                                                command_failed = 1;
        !          3984:                                        }
        !          3985:                                        PQclear(pgsql_result);
        !          3986:                                }
        !          3987:                                if (command_failed) {
        !          3988:                                        RETURN_FALSE;
        !          3989:                                }
        !          3990:                        } else {
        !          3991:                                PQclear(pgsql_result);
        !          3992:                                RETURN_FALSE;
        !          3993:                        }
        !          3994:                        RETURN_TRUE;
        !          3995:                        break;
        !          3996:                default:
        !          3997:                        PQclear(pgsql_result);
        !          3998:                        PHP_PQ_ERROR("Copy command failed: %s", pgsql);
        !          3999:                        RETURN_FALSE;
        !          4000:                        break;
        !          4001:        }
        !          4002: }
        !          4003: /* }}} */
        !          4004: 
        !          4005: #ifdef HAVE_PQESCAPE
        !          4006: /* {{{ proto string pg_escape_string([resource connection,] string data)
        !          4007:    Escape string for text/char type */
        !          4008: PHP_FUNCTION(pg_escape_string)
        !          4009: {
        !          4010:        char *from = NULL, *to = NULL;
        !          4011:        zval *pgsql_link;
        !          4012: #ifdef HAVE_PQESCAPE_CONN
        !          4013:        PGconn *pgsql;
        !          4014: #endif
        !          4015:        int to_len;
        !          4016:        int from_len;
        !          4017:        int id = -1;
        !          4018: 
        !          4019:        switch (ZEND_NUM_ARGS()) {
        !          4020:                case 1:
        !          4021:                        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &from, &from_len) == FAILURE) {
        !          4022:                                return;
        !          4023:                        }
        !          4024:                        pgsql_link = NULL;
        !          4025:                        id = PGG(default_link);
        !          4026:                        break;
        !          4027: 
        !          4028:                default:
        !          4029:                        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pgsql_link, &from, &from_len) == FAILURE) {
        !          4030:                                return;
        !          4031:                        }
        !          4032:                        break;
        !          4033:        }
        !          4034: 
        !          4035:        to = (char *) safe_emalloc(from_len, 2, 1);
        !          4036: 
        !          4037: #ifdef HAVE_PQESCAPE_CONN
        !          4038:        if (pgsql_link != NULL || id != -1) {
        !          4039:                ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          4040:                to_len = (int) PQescapeStringConn(pgsql, to, from, (size_t)from_len, NULL);
        !          4041:        } else  
        !          4042: #endif
        !          4043:                to_len = (int) PQescapeString(to, from, (size_t)from_len);
        !          4044: 
        !          4045:        RETURN_STRINGL(to, to_len, 0);
        !          4046: }
        !          4047: /* }}} */
        !          4048: 
        !          4049: /* {{{ proto string pg_escape_bytea([resource connection,] string data)
        !          4050:    Escape binary for bytea type  */
        !          4051: PHP_FUNCTION(pg_escape_bytea)
        !          4052: {
        !          4053:        char *from = NULL, *to = NULL;
        !          4054:        size_t to_len;
        !          4055:        int from_len, id = -1;
        !          4056: #ifdef HAVE_PQESCAPE_BYTEA_CONN
        !          4057:        PGconn *pgsql;
        !          4058: #endif
        !          4059:        zval *pgsql_link;
        !          4060: 
        !          4061:        switch (ZEND_NUM_ARGS()) {
        !          4062:                case 1:
        !          4063:                        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &from, &from_len) == FAILURE) {
        !          4064:                                return;
        !          4065:                        }
        !          4066:                        pgsql_link = NULL;
        !          4067:                        id = PGG(default_link);
        !          4068:                        break;
        !          4069: 
        !          4070:                default:
        !          4071:                        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pgsql_link, &from, &from_len) == FAILURE) {
        !          4072:                                return;
        !          4073:                        }
        !          4074:                        break;
        !          4075:        }
        !          4076: 
        !          4077: #ifdef HAVE_PQESCAPE_BYTEA_CONN
        !          4078:        if (pgsql_link != NULL || id != -1) {
        !          4079:                ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          4080:                to = (char *)PQescapeByteaConn(pgsql, from, (size_t)from_len, &to_len);
        !          4081:        } else
        !          4082: #endif
        !          4083:                to = (char *)PQescapeBytea((unsigned char*)from, from_len, &to_len);
        !          4084: 
        !          4085:        RETVAL_STRINGL(to, to_len-1, 1); /* to_len includes addtional '\0' */
        !          4086:        PQfreemem(to);
        !          4087: }
        !          4088: /* }}} */
        !          4089: 
        !          4090: #if !HAVE_PQUNESCAPEBYTEA
        !          4091: /* PQunescapeBytea() from PostgreSQL 7.3 to provide bytea unescape feature to 7.2 users.
        !          4092:    Renamed to php_pgsql_unescape_bytea() */
        !          4093: /*
        !          4094:  *             PQunescapeBytea - converts the null terminated string representation
        !          4095:  *             of a bytea, strtext, into binary, filling a buffer. It returns a
        !          4096:  *             pointer to the buffer which is NULL on error, and the size of the
        !          4097:  *             buffer in retbuflen. The pointer may subsequently be used as an
        !          4098:  *             argument to the function free(3). It is the reverse of PQescapeBytea.
        !          4099:  *
        !          4100:  *             The following transformations are reversed:
        !          4101:  *             '\0' == ASCII  0 == \000
        !          4102:  *             '\'' == ASCII 39 == \'
        !          4103:  *             '\\' == ASCII 92 == \\
        !          4104:  *
        !          4105:  *             States:
        !          4106:  *             0       normal          0->1->2->3->4
        !          4107:  *             1       \                          1->5
        !          4108:  *             2       \0                         1->6
        !          4109:  *             3       \00
        !          4110:  *             4       \000
        !          4111:  *             5       \'
        !          4112:  *             6       \\
        !          4113:  */
        !          4114: static unsigned char * php_pgsql_unescape_bytea(unsigned char *strtext, size_t *retbuflen)
        !          4115: {
        !          4116:        size_t          buflen;
        !          4117:        unsigned char *buffer,
        !          4118:                           *sp,
        !          4119:                           *bp;
        !          4120:        unsigned int state = 0;
        !          4121: 
        !          4122:        if (strtext == NULL)
        !          4123:                return NULL;
        !          4124:        buflen = strlen(strtext);       /* will shrink, also we discover if
        !          4125:                                                                 * strtext */
        !          4126:        buffer = (unsigned char *) emalloc(buflen);     /* isn't NULL terminated */
        !          4127:        for (bp = buffer, sp = strtext; *sp != '\0'; bp++, sp++)
        !          4128:        {
        !          4129:                switch (state)
        !          4130:                {
        !          4131:                        case 0:
        !          4132:                                if (*sp == '\\')
        !          4133:                                        state = 1;
        !          4134:                                *bp = *sp;
        !          4135:                                break;
        !          4136:                        case 1:
        !          4137:                                if (*sp == '\'')        /* state=5 */
        !          4138:                                {                               /* replace \' with 39 */
        !          4139:                                        bp--;
        !          4140:                                        *bp = '\'';
        !          4141:                                        buflen--;
        !          4142:                                        state = 0;
        !          4143:                                }
        !          4144:                                else if (*sp == '\\')   /* state=6 */
        !          4145:                                {                               /* replace \\ with 92 */
        !          4146:                                        bp--;
        !          4147:                                        *bp = '\\';
        !          4148:                                        buflen--;
        !          4149:                                        state = 0;
        !          4150:                                }
        !          4151:                                else
        !          4152:                                {
        !          4153:                                        if (isdigit(*sp))
        !          4154:                                                state = 2;
        !          4155:                                        else
        !          4156:                                                state = 0;
        !          4157:                                        *bp = *sp;
        !          4158:                                }
        !          4159:                                break;
        !          4160:                        case 2:
        !          4161:                                if (isdigit(*sp))
        !          4162:                                        state = 3;
        !          4163:                                else
        !          4164:                                        state = 0;
        !          4165:                                *bp = *sp;
        !          4166:                                break;
        !          4167:                        case 3:
        !          4168:                                if (isdigit(*sp))               /* state=4 */
        !          4169:                                {
        !          4170:                                        unsigned char *start, *end, buf[4]; /* 000 + '\0' */
        !          4171:                                        
        !          4172:                                        bp -= 3;
        !          4173:                                        memcpy(buf, sp-2, 3);
        !          4174:                                        buf[3] = '\0';
        !          4175:                                        start = buf;
        !          4176:                                        *bp = (unsigned char)strtoul(start, (char **)&end, 8);
        !          4177:                                        buflen -= 3;
        !          4178:                                        state = 0;
        !          4179:                                }
        !          4180:                                else
        !          4181:                                {
        !          4182:                                        *bp = *sp;
        !          4183:                                        state = 0;
        !          4184:                                }
        !          4185:                                break;
        !          4186:                }
        !          4187:        }
        !          4188:        buffer = erealloc(buffer, buflen+1);
        !          4189:        buffer[buflen] = '\0';
        !          4190: 
        !          4191:        *retbuflen = buflen;
        !          4192:        return buffer;
        !          4193: }
        !          4194: #endif
        !          4195: 
        !          4196: /* {{{ proto string pg_unescape_bytea(string data)
        !          4197:    Unescape binary for bytea type  */
        !          4198: PHP_FUNCTION(pg_unescape_bytea)
        !          4199: {
        !          4200:        char *from = NULL, *to = NULL, *tmp = NULL;
        !          4201:        size_t to_len;
        !          4202:        int from_len;
        !          4203:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
        !          4204:                                                          &from, &from_len) == FAILURE) {
        !          4205:                return;
        !          4206:        }
        !          4207: 
        !          4208: #if HAVE_PQUNESCAPEBYTEA
        !          4209:        tmp = (char *)PQunescapeBytea((unsigned char*)from, &to_len);
        !          4210:        to = estrndup(tmp, to_len);
        !          4211:        PQfreemem(tmp);
        !          4212: #else
        !          4213:        to = (char *)php_pgsql_unescape_bytea((unsigned char*)from, &to_len);
        !          4214: #endif
        !          4215:        if (!to) {
        !          4216:                RETURN_FALSE;
        !          4217:        }
        !          4218:        RETVAL_STRINGL(to, to_len, 0);
        !          4219: }
        !          4220: /* }}} */
        !          4221: #endif
        !          4222: 
        !          4223: /* {{{ proto string pg_result_error(resource result)
        !          4224:    Get error message associated with result */
        !          4225: PHP_FUNCTION(pg_result_error)
        !          4226: {
        !          4227:        zval *result;
        !          4228:        PGresult *pgsql_result;
        !          4229:        pgsql_result_handle *pg_result;
        !          4230:        char *err = NULL;
        !          4231: 
        !          4232:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
        !          4233:                                                                 &result) == FAILURE) {
        !          4234:                RETURN_FALSE;
        !          4235:        }
        !          4236:        
        !          4237:        ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
        !          4238: 
        !          4239:        pgsql_result = pg_result->result;
        !          4240:        if (!pgsql_result) {
        !          4241:                RETURN_FALSE;
        !          4242:        }
        !          4243:        err = (char *)PQresultErrorMessage(pgsql_result);
        !          4244:        RETURN_STRING(err,1);
        !          4245: }
        !          4246: /* }}} */
        !          4247: 
        !          4248: #if HAVE_PQRESULTERRORFIELD
        !          4249: /* {{{ proto string pg_result_error_field(resource result, int fieldcode)
        !          4250:    Get error message field associated with result */
        !          4251: PHP_FUNCTION(pg_result_error_field)
        !          4252: {
        !          4253:        zval *result;
        !          4254:        long fieldcode;
        !          4255:        PGresult *pgsql_result;
        !          4256:        pgsql_result_handle *pg_result;
        !          4257:        char *field = NULL;
        !          4258: 
        !          4259:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "rl",
        !          4260:                                                                 &result, &fieldcode) == FAILURE) {
        !          4261:                RETURN_FALSE;
        !          4262:        }
        !          4263:        
        !          4264:        ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
        !          4265: 
        !          4266:        pgsql_result = pg_result->result;
        !          4267:        if (!pgsql_result) {
        !          4268:                RETURN_FALSE;
        !          4269:        }
        !          4270:        if (fieldcode & (PG_DIAG_SEVERITY|PG_DIAG_SQLSTATE|PG_DIAG_MESSAGE_PRIMARY|PG_DIAG_MESSAGE_DETAIL
        !          4271:                                |PG_DIAG_MESSAGE_HINT|PG_DIAG_STATEMENT_POSITION
        !          4272: #if PG_DIAG_INTERNAL_POSITION
        !          4273:                                |PG_DIAG_INTERNAL_POSITION
        !          4274: #endif
        !          4275: #if PG_DIAG_INTERNAL_QUERY
        !          4276:                                |PG_DIAG_INTERNAL_QUERY
        !          4277: #endif
        !          4278:                                |PG_DIAG_CONTEXT|PG_DIAG_SOURCE_FILE|PG_DIAG_SOURCE_LINE
        !          4279:                                |PG_DIAG_SOURCE_FUNCTION)) {
        !          4280:                field = (char *)PQresultErrorField(pgsql_result, fieldcode);
        !          4281:                if (field == NULL) {
        !          4282:                        RETURN_NULL();
        !          4283:                } else {
        !          4284:                        RETURN_STRING(field, 1);
        !          4285:                }
        !          4286:        } else {
        !          4287:                RETURN_FALSE;
        !          4288:        }
        !          4289: }
        !          4290: /* }}} */
        !          4291: #endif
        !          4292: 
        !          4293: /* {{{ proto int pg_connection_status(resource connection)
        !          4294:    Get connection status */
        !          4295: PHP_FUNCTION(pg_connection_status)
        !          4296: {
        !          4297:        zval *pgsql_link = NULL;
        !          4298:        int id = -1;
        !          4299:        PGconn *pgsql;
        !          4300: 
        !          4301:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
        !          4302:                                                                 &pgsql_link) == FAILURE) {
        !          4303:                RETURN_FALSE;
        !          4304:        }
        !          4305: 
        !          4306:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          4307: 
        !          4308:        RETURN_LONG(PQstatus(pgsql));
        !          4309: }
        !          4310: 
        !          4311: /* }}} */
        !          4312: 
        !          4313: #if HAVE_PGTRANSACTIONSTATUS
        !          4314: /* {{{ proto int pg_transaction_status(resource connection)
        !          4315:    Get transaction status */
        !          4316: PHP_FUNCTION(pg_transaction_status)
        !          4317: {
        !          4318:        zval *pgsql_link = NULL;
        !          4319:        int id = -1;
        !          4320:        PGconn *pgsql;
        !          4321: 
        !          4322:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
        !          4323:                                                                 &pgsql_link) == FAILURE) {
        !          4324:                RETURN_FALSE;
        !          4325:        }
        !          4326: 
        !          4327:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          4328: 
        !          4329:        RETURN_LONG(PQtransactionStatus(pgsql));
        !          4330: }
        !          4331: #endif
        !          4332: 
        !          4333: /* }}} */
        !          4334: 
        !          4335: /* {{{ proto bool pg_connection_reset(resource connection)
        !          4336:    Reset connection (reconnect) */
        !          4337: PHP_FUNCTION(pg_connection_reset)
        !          4338: {
        !          4339:        zval *pgsql_link;
        !          4340:        int id = -1;
        !          4341:        PGconn *pgsql;
        !          4342:        
        !          4343:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
        !          4344:                                                                 &pgsql_link) == FAILURE) {
        !          4345:                RETURN_FALSE;
        !          4346:        }
        !          4347: 
        !          4348:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          4349:        
        !          4350:        PQreset(pgsql);
        !          4351:        if (PQstatus(pgsql) == CONNECTION_BAD) {
        !          4352:                RETURN_FALSE;
        !          4353:        }
        !          4354:        RETURN_TRUE;
        !          4355: }
        !          4356: 
        !          4357: /* }}} */
        !          4358: 
        !          4359: #define PHP_PG_ASYNC_IS_BUSY           1
        !          4360: #define PHP_PG_ASYNC_REQUEST_CANCEL 2
        !          4361:                                                                                                                  
        !          4362: /* {{{ php_pgsql_flush_query
        !          4363:  */
        !          4364: static int php_pgsql_flush_query(PGconn *pgsql TSRMLS_DC) 
        !          4365: {
        !          4366:        PGresult *res;
        !          4367:        int leftover = 0;
        !          4368:        
        !          4369:        if (PQ_SETNONBLOCKING(pgsql, 1)) {
        !          4370:                php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to nonblocking mode");
        !          4371:                return -1;
        !          4372:        }
        !          4373:        while ((res = PQgetResult(pgsql))) {
        !          4374:                PQclear(res);
        !          4375:                leftover++;
        !          4376:        }
        !          4377:        PQ_SETNONBLOCKING(pgsql, 0);
        !          4378:        return leftover;
        !          4379: }
        !          4380: /* }}} */
        !          4381:                                                                                                                  
        !          4382: /* {{{ php_pgsql_do_async
        !          4383:  */
        !          4384: static void php_pgsql_do_async(INTERNAL_FUNCTION_PARAMETERS, int entry_type) 
        !          4385: {
        !          4386:        zval *pgsql_link;
        !          4387:        int id = -1;
        !          4388:        PGconn *pgsql;
        !          4389:        PGresult *pgsql_result;
        !          4390: 
        !          4391:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
        !          4392:                                                                 &pgsql_link) == FAILURE) {
        !          4393:                RETURN_FALSE;
        !          4394:        }
        !          4395: 
        !          4396:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          4397: 
        !          4398:        if (PQ_SETNONBLOCKING(pgsql, 1)) {
        !          4399:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to nonblocking mode");
        !          4400:                RETURN_FALSE;
        !          4401:        }
        !          4402:        switch(entry_type) {
        !          4403:                case PHP_PG_ASYNC_IS_BUSY:
        !          4404:                        PQconsumeInput(pgsql);
        !          4405:                        Z_LVAL_P(return_value) = PQisBusy(pgsql);
        !          4406:                        Z_TYPE_P(return_value) = IS_LONG;
        !          4407:                        break;
        !          4408:                case PHP_PG_ASYNC_REQUEST_CANCEL:
        !          4409:                        Z_LVAL_P(return_value) = PQrequestCancel(pgsql);
        !          4410:                        Z_TYPE_P(return_value) = IS_LONG;
        !          4411:                        while ((pgsql_result = PQgetResult(pgsql))) {
        !          4412:                                PQclear(pgsql_result);
        !          4413:                        }
        !          4414:                        break;
        !          4415:                default:
        !          4416:                        php_error_docref(NULL TSRMLS_CC, E_ERROR, "PostgreSQL module error, please report this error");
        !          4417:                        break;
        !          4418:        }
        !          4419:        if (PQ_SETNONBLOCKING(pgsql, 0)) {
        !          4420:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
        !          4421:        }
        !          4422:        convert_to_boolean_ex(&return_value);
        !          4423: }
        !          4424: /* }}} */
        !          4425: 
        !          4426: /* {{{ proto bool pg_cancel_query(resource connection)
        !          4427:    Cancel request */
        !          4428: PHP_FUNCTION(pg_cancel_query)
        !          4429: {
        !          4430:        php_pgsql_do_async(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_ASYNC_REQUEST_CANCEL);
        !          4431: }
        !          4432: /* }}} */
        !          4433: 
        !          4434: /* {{{ proto bool pg_connection_busy(resource connection)
        !          4435:    Get connection is busy or not */
        !          4436: PHP_FUNCTION(pg_connection_busy)
        !          4437: {
        !          4438:        php_pgsql_do_async(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_ASYNC_IS_BUSY);
        !          4439: }
        !          4440: /* }}} */
        !          4441: 
        !          4442: /* {{{ proto bool pg_send_query(resource connection, string query)
        !          4443:    Send asynchronous query */
        !          4444: PHP_FUNCTION(pg_send_query)
        !          4445: {
        !          4446:        zval *pgsql_link;
        !          4447:        char *query;
        !          4448:        int len;
        !          4449:        int id = -1;
        !          4450:        PGconn *pgsql;
        !          4451:        PGresult *res;
        !          4452:        int leftover = 0;
        !          4453: 
        !          4454:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs",
        !          4455:                                                          &pgsql_link, &query, &len) == FAILURE) {
        !          4456:                return;
        !          4457:        }
        !          4458: 
        !          4459:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          4460: 
        !          4461:        if (PQ_SETNONBLOCKING(pgsql, 1)) {
        !          4462:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to nonblocking mode");
        !          4463:                RETURN_FALSE;
        !          4464:        }
        !          4465:        while ((res = PQgetResult(pgsql))) {
        !          4466:                PQclear(res);
        !          4467:                leftover = 1;
        !          4468:        }
        !          4469:        if (leftover) {
        !          4470:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "There are results on this connection. Call pg_get_result() until it returns FALSE");
        !          4471:        }
        !          4472:        if (!PQsendQuery(pgsql, query)) {
        !          4473:                if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
        !          4474:                        PQreset(pgsql);
        !          4475:                }
        !          4476:                if (!PQsendQuery(pgsql, query)) {
        !          4477:                        RETURN_FALSE;
        !          4478:                }
        !          4479:        }
        !          4480:        if (PQ_SETNONBLOCKING(pgsql, 0)) {
        !          4481:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
        !          4482:        }
        !          4483:        RETURN_TRUE;
        !          4484: }
        !          4485: /* }}} */
        !          4486: 
        !          4487: #if HAVE_PQSENDQUERYPARAMS
        !          4488: /* {{{ proto bool pg_send_query_params(resource connection, string query, array params)
        !          4489:    Send asynchronous parameterized query */
        !          4490: PHP_FUNCTION(pg_send_query_params)
        !          4491: {
        !          4492:        zval *pgsql_link, *pv_param_arr, **tmp;
        !          4493:        int num_params = 0;
        !          4494:        char **params = NULL;
        !          4495:        char *query;
        !          4496:        int query_len, id = -1;
        !          4497:        PGconn *pgsql;
        !          4498:        PGresult *res;
        !          4499:        int leftover = 0;
        !          4500: 
        !          4501:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsa/", &pgsql_link, &query, &query_len, &pv_param_arr) == FAILURE) {
        !          4502:                return;
        !          4503:        }
        !          4504: 
        !          4505:        if (pgsql_link == NULL && id == -1) {
        !          4506:                RETURN_FALSE;
        !          4507:        }
        !          4508: 
        !          4509:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          4510: 
        !          4511:        if (PQ_SETNONBLOCKING(pgsql, 1)) {
        !          4512:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to nonblocking mode");
        !          4513:                RETURN_FALSE;
        !          4514:        }
        !          4515:        while ((res = PQgetResult(pgsql))) {
        !          4516:                PQclear(res);
        !          4517:                leftover = 1;
        !          4518:        }
        !          4519:        if (leftover) {
        !          4520:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "There are results on this connection. Call pg_get_result() until it returns FALSE");
        !          4521:        }
        !          4522: 
        !          4523:        zend_hash_internal_pointer_reset(Z_ARRVAL_P(pv_param_arr));
        !          4524:        num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr));
        !          4525:        if (num_params > 0) {
        !          4526:                int i = 0;
        !          4527:                params = (char **)safe_emalloc(sizeof(char *), num_params, 0);
        !          4528:                
        !          4529:                for(i = 0; i < num_params; i++) {
        !          4530:                        if (zend_hash_get_current_data(Z_ARRVAL_P(pv_param_arr), (void **) &tmp) == FAILURE) {
        !          4531:                                php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error getting parameter");
        !          4532:                                _php_pgsql_free_params(params, num_params);
        !          4533:                                RETURN_FALSE;
        !          4534:                        }
        !          4535: 
        !          4536:                        if (Z_TYPE_PP(tmp) == IS_NULL) {
        !          4537:                                params[i] = NULL;
        !          4538:                        } else {
        !          4539:                                zval tmp_val = **tmp;
        !          4540:                                zval_copy_ctor(&tmp_val);
        !          4541:                                convert_to_string(&tmp_val);
        !          4542:                                if (Z_TYPE(tmp_val) != IS_STRING) {
        !          4543:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error converting parameter");
        !          4544:                                        zval_dtor(&tmp_val);
        !          4545:                                        _php_pgsql_free_params(params, num_params);
        !          4546:                                        RETURN_FALSE;
        !          4547:                                }
        !          4548:                                params[i] = estrndup(Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
        !          4549:                                zval_dtor(&tmp_val);
        !          4550:                        }
        !          4551: 
        !          4552:                        zend_hash_move_forward(Z_ARRVAL_P(pv_param_arr));
        !          4553:                }
        !          4554:        }
        !          4555: 
        !          4556:        if (!PQsendQueryParams(pgsql, query, num_params, NULL, (const char * const *)params, NULL, NULL, 0)) {
        !          4557:                if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
        !          4558:                        PQreset(pgsql);
        !          4559:                }
        !          4560:                if (!PQsendQueryParams(pgsql, query, num_params, NULL, (const char * const *)params, NULL, NULL, 0)) {
        !          4561:                        _php_pgsql_free_params(params, num_params);
        !          4562:                        RETURN_FALSE;
        !          4563:                }
        !          4564:        }
        !          4565:        _php_pgsql_free_params(params, num_params);
        !          4566:        if (PQ_SETNONBLOCKING(pgsql, 0)) {
        !          4567:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
        !          4568:        }
        !          4569:        RETURN_TRUE;
        !          4570: }
        !          4571: /* }}} */
        !          4572: #endif
        !          4573: 
        !          4574: #if HAVE_PQSENDPREPARE
        !          4575: /* {{{ proto bool pg_send_prepare(resource connection, string stmtname, string query)
        !          4576:    Asynchronously prepare a query for future execution */
        !          4577: PHP_FUNCTION(pg_send_prepare)
        !          4578: {
        !          4579:        zval *pgsql_link;
        !          4580:        char *query, *stmtname;
        !          4581:        int stmtname_len, query_len, id = -1;
        !          4582:        PGconn *pgsql;
        !          4583:        PGresult *res;
        !          4584:        int leftover = 0;
        !          4585: 
        !          4586:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &pgsql_link, &stmtname, &stmtname_len, &query, &query_len) == FAILURE) {
        !          4587:                return;
        !          4588:        }
        !          4589: 
        !          4590:        if (pgsql_link == NULL && id == -1) {
        !          4591:                RETURN_FALSE;
        !          4592:        }       
        !          4593: 
        !          4594:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          4595: 
        !          4596:        if (PQ_SETNONBLOCKING(pgsql, 1)) {
        !          4597:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to nonblocking mode");
        !          4598:                RETURN_FALSE;
        !          4599:        }
        !          4600:        while ((res = PQgetResult(pgsql))) {
        !          4601:                PQclear(res);
        !          4602:                leftover = 1;
        !          4603:        }
        !          4604:        if (leftover) {
        !          4605:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "There are results on this connection. Call pg_get_result() until it returns FALSE");
        !          4606:        }
        !          4607:        if (!PQsendPrepare(pgsql, stmtname, query, 0, NULL)) {
        !          4608:                if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
        !          4609:                        PQreset(pgsql);
        !          4610:                }
        !          4611:                if (!PQsendPrepare(pgsql, stmtname, query, 0, NULL)) {
        !          4612:                        RETURN_FALSE;
        !          4613:                }
        !          4614:        }
        !          4615:        if (PQ_SETNONBLOCKING(pgsql, 0)) {
        !          4616:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
        !          4617:        }
        !          4618:        RETURN_TRUE;
        !          4619: }
        !          4620: /* }}} */
        !          4621: #endif
        !          4622: 
        !          4623: #if HAVE_PQSENDQUERYPREPARED
        !          4624: /* {{{ proto bool pg_send_execute(resource connection, string stmtname, array params)
        !          4625:    Executes prevriously prepared stmtname asynchronously */
        !          4626: PHP_FUNCTION(pg_send_execute)
        !          4627: {
        !          4628:        zval *pgsql_link;
        !          4629:        zval *pv_param_arr, **tmp;
        !          4630:        int num_params = 0;
        !          4631:        char **params = NULL;
        !          4632:        char *stmtname;
        !          4633:        int stmtname_len, id = -1;
        !          4634:        PGconn *pgsql;
        !          4635:        PGresult *res;
        !          4636:        int leftover = 0;
        !          4637: 
        !          4638:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsa", &pgsql_link, &stmtname, &stmtname_len, &pv_param_arr) == FAILURE) {
        !          4639:                return;
        !          4640:        }
        !          4641: 
        !          4642:        if (pgsql_link == NULL && id == -1) {
        !          4643:                RETURN_FALSE;
        !          4644:        }
        !          4645: 
        !          4646:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          4647: 
        !          4648:        if (PQ_SETNONBLOCKING(pgsql, 1)) {
        !          4649:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to nonblocking mode");
        !          4650:                RETURN_FALSE;
        !          4651:        }
        !          4652:        while ((res = PQgetResult(pgsql))) {
        !          4653:                PQclear(res);
        !          4654:                leftover = 1;
        !          4655:        }
        !          4656:        if (leftover) {
        !          4657:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "There are results on this connection. Call pg_get_result() until it returns FALSE");
        !          4658:        }
        !          4659: 
        !          4660:        zend_hash_internal_pointer_reset(Z_ARRVAL_P(pv_param_arr));
        !          4661:        num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr));
        !          4662:        if (num_params > 0) {
        !          4663:                int i = 0;
        !          4664:                params = (char **)safe_emalloc(sizeof(char *), num_params, 0);
        !          4665:                
        !          4666:                for(i = 0; i < num_params; i++) {
        !          4667:                        if (zend_hash_get_current_data(Z_ARRVAL_P(pv_param_arr), (void **) &tmp) == FAILURE) {
        !          4668:                                php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error getting parameter");
        !          4669:                                _php_pgsql_free_params(params, num_params);
        !          4670:                                RETURN_FALSE;
        !          4671:                        }
        !          4672: 
        !          4673:                        if (Z_TYPE_PP(tmp) == IS_NULL) {
        !          4674:                                params[i] = NULL;
        !          4675:                        } else {
        !          4676:                                zval tmp_val = **tmp;
        !          4677:                                zval_copy_ctor(&tmp_val);
        !          4678:                                convert_to_string(&tmp_val);
        !          4679:                                if (Z_TYPE(tmp_val) != IS_STRING) {
        !          4680:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error converting parameter");
        !          4681:                                        zval_dtor(&tmp_val);
        !          4682:                                        _php_pgsql_free_params(params, num_params);
        !          4683:                                        RETURN_FALSE;
        !          4684:                                }
        !          4685:                                params[i] = estrndup(Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
        !          4686:                                zval_dtor(&tmp_val);
        !          4687:                        }
        !          4688: 
        !          4689:                        zend_hash_move_forward(Z_ARRVAL_P(pv_param_arr));
        !          4690:                }
        !          4691:        }
        !          4692: 
        !          4693:        if (!PQsendQueryPrepared(pgsql, stmtname, num_params, (const char * const *)params, NULL, NULL, 0)) {
        !          4694:                if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
        !          4695:                        PQreset(pgsql);
        !          4696:                }
        !          4697:                if (!PQsendQueryPrepared(pgsql, stmtname, num_params, (const char * const *)params, NULL, NULL, 0)) {
        !          4698:                        _php_pgsql_free_params(params, num_params);
        !          4699:                        RETURN_FALSE;
        !          4700:                }
        !          4701:        }
        !          4702:        _php_pgsql_free_params(params, num_params);
        !          4703:        if (PQ_SETNONBLOCKING(pgsql, 0)) {
        !          4704:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
        !          4705:        }
        !          4706:        RETURN_TRUE;
        !          4707: }
        !          4708: /* }}} */
        !          4709: #endif
        !          4710: 
        !          4711: /* {{{ proto resource pg_get_result(resource connection)
        !          4712:    Get asynchronous query result */
        !          4713: PHP_FUNCTION(pg_get_result)
        !          4714: {
        !          4715:        zval *pgsql_link;
        !          4716:        int id = -1;
        !          4717:        PGconn *pgsql;
        !          4718:        PGresult *pgsql_result;
        !          4719:        pgsql_result_handle *pg_result;
        !          4720: 
        !          4721:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r", &pgsql_link) == FAILURE) {
        !          4722:                RETURN_FALSE;
        !          4723:        }
        !          4724: 
        !          4725:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          4726:        
        !          4727:        pgsql_result = PQgetResult(pgsql);
        !          4728:        if (!pgsql_result) {
        !          4729:                /* no result */
        !          4730:                RETURN_FALSE;
        !          4731:        }
        !          4732:        pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle));
        !          4733:        pg_result->conn = pgsql;
        !          4734:        pg_result->result = pgsql_result;
        !          4735:        pg_result->row = 0;
        !          4736:        ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result);
        !          4737: }
        !          4738: /* }}} */
        !          4739: 
        !          4740: /* {{{ proto mixed pg_result_status(resource result[, long result_type])
        !          4741:    Get status of query result */
        !          4742: PHP_FUNCTION(pg_result_status)
        !          4743: {
        !          4744:        zval *result;
        !          4745:        long result_type = PGSQL_STATUS_LONG;
        !          4746:        ExecStatusType status;
        !          4747:        PGresult *pgsql_result;
        !          4748:        pgsql_result_handle *pg_result;
        !          4749: 
        !          4750:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r|l",
        !          4751:                                                                 &result, &result_type) == FAILURE) {
        !          4752:                RETURN_FALSE;
        !          4753:        }
        !          4754: 
        !          4755:        ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
        !          4756: 
        !          4757:        pgsql_result = pg_result->result;
        !          4758:        if (result_type == PGSQL_STATUS_LONG) {
        !          4759:                status = PQresultStatus(pgsql_result);
        !          4760:                RETURN_LONG((int)status);
        !          4761:        }
        !          4762:        else if (result_type == PGSQL_STATUS_STRING) {
        !          4763:                RETURN_STRING(PQcmdStatus(pgsql_result), 1);
        !          4764:        }
        !          4765:        else {
        !          4766:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Optional 2nd parameter should be PGSQL_STATUS_LONG or PGSQL_STATUS_STRING");
        !          4767:                RETURN_FALSE;
        !          4768:        }
        !          4769: }
        !          4770: /* }}} */
        !          4771: 
        !          4772: 
        !          4773: /* {{{ proto array pg_get_notify([resource connection[, result_type]])
        !          4774:    Get asynchronous notification */
        !          4775: PHP_FUNCTION(pg_get_notify)
        !          4776: {
        !          4777:        zval *pgsql_link;
        !          4778:        int id = -1;
        !          4779:        long result_type = PGSQL_ASSOC;
        !          4780:        PGconn *pgsql;
        !          4781:        PGnotify *pgsql_notify;
        !          4782: 
        !          4783:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r|l",
        !          4784:                                                                 &pgsql_link, &result_type) == FAILURE) {
        !          4785:                RETURN_FALSE;
        !          4786:        }
        !          4787: 
        !          4788:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          4789: 
        !          4790:        if (!(result_type & PGSQL_BOTH)) {
        !          4791:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid result type");
        !          4792:                RETURN_FALSE;
        !          4793:        }
        !          4794: 
        !          4795:        PQconsumeInput(pgsql);
        !          4796:        pgsql_notify = PQnotifies(pgsql);
        !          4797:        if (!pgsql_notify) {
        !          4798:                /* no notify message */
        !          4799:                RETURN_FALSE;
        !          4800:        }
        !          4801:        array_init(return_value);
        !          4802:        if (result_type & PGSQL_NUM) {
        !          4803:                add_index_string(return_value, 0, pgsql_notify->relname, 1);
        !          4804:                add_index_long(return_value, 1, pgsql_notify->be_pid);
        !          4805: #if HAVE_PQPROTOCOLVERSION && HAVE_PQPARAMETERSTATUS 
        !          4806:                if (PQprotocolVersion(pgsql) >= 3 && atof(PQparameterStatus(pgsql, "server_version")) >= 9.0) {
        !          4807: #else 
        !          4808:                if (atof(PG_VERSION) >= 9.0) {
        !          4809: #endif 
        !          4810:                        add_index_string(return_value, 2, pgsql_notify->extra, 1);
        !          4811:                }
        !          4812:        }
        !          4813:        if (result_type & PGSQL_ASSOC) {
        !          4814:                add_assoc_string(return_value, "message", pgsql_notify->relname, 1);
        !          4815:                add_assoc_long(return_value, "pid", pgsql_notify->be_pid);
        !          4816: #if HAVE_PQPROTOCOLVERSION && HAVE_PQPARAMETERSTATUS 
        !          4817:                if (PQprotocolVersion(pgsql) >= 3 && atof(PQparameterStatus(pgsql, "server_version")) >= 9.0) {
        !          4818: #else 
        !          4819:                if (atof(PG_VERSION) >= 9.0) {
        !          4820: #endif 
        !          4821:                        add_assoc_string(return_value, "payload", pgsql_notify->extra, 1);
        !          4822:                }
        !          4823:        }
        !          4824:        PQfreemem(pgsql_notify);
        !          4825: }
        !          4826: /* }}} */
        !          4827: 
        !          4828: /* {{{ proto int pg_get_pid([resource connection)
        !          4829:    Get backend(server) pid */
        !          4830: PHP_FUNCTION(pg_get_pid)
        !          4831: {
        !          4832:        zval *pgsql_link;
        !          4833:        int id = -1;
        !          4834:        PGconn *pgsql;
        !          4835: 
        !          4836:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
        !          4837:                                                                 &pgsql_link) == FAILURE) {
        !          4838:                RETURN_FALSE;
        !          4839:        }
        !          4840: 
        !          4841:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          4842: 
        !          4843:        RETURN_LONG(PQbackendPID(pgsql));
        !          4844: }
        !          4845: /* }}} */
        !          4846: 
        !          4847: /* {{{ php_pgsql_meta_data
        !          4848:  * TODO: Add meta_data cache for better performance
        !          4849:  */
        !          4850: PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, zval *meta TSRMLS_DC) 
        !          4851: {
        !          4852:        PGresult *pg_result;
        !          4853:        char *src, *tmp_name, *tmp_name2 = NULL;
        !          4854:        smart_str querystr = {0};
        !          4855:        int new_len;
        !          4856:        int i, num_rows;
        !          4857:        zval *elem;
        !          4858:        
        !          4859:        if (!*table_name) {
        !          4860:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "The table name must be specified");
        !          4861:                return FAILURE;
        !          4862:        }
        !          4863: 
        !          4864:        src = estrdup(table_name);
        !          4865:        tmp_name = php_strtok_r(src, ".", &tmp_name2);
        !          4866:        
        !          4867:        if (!tmp_name2 || !*tmp_name2) {
        !          4868:                /* Default schema */
        !          4869:                tmp_name2 = tmp_name;
        !          4870:                tmp_name = "public";
        !          4871:        }
        !          4872: 
        !          4873:        smart_str_appends(&querystr, 
        !          4874:                        "SELECT a.attname, a.attnum, t.typname, a.attlen, a.attnotNULL, a.atthasdef, a.attndims "
        !          4875:                        "FROM pg_class as c, pg_attribute a, pg_type t, pg_namespace n "
        !          4876:                        "WHERE a.attnum > 0 AND a.attrelid = c.oid AND c.relname = '");
        !          4877:        tmp_name2 = php_addslashes(tmp_name2, strlen(tmp_name2), &new_len, 0 TSRMLS_CC);
        !          4878:        smart_str_appendl(&querystr, tmp_name2, new_len);
        !          4879:        
        !          4880:        smart_str_appends(&querystr, "' AND c.relnamespace = n.oid AND n.nspname = '");
        !          4881:        tmp_name = php_addslashes(tmp_name, strlen(tmp_name), &new_len, 0 TSRMLS_CC);
        !          4882:        smart_str_appendl(&querystr, tmp_name, new_len);
        !          4883: 
        !          4884:        smart_str_appends(&querystr, "' AND a.atttypid = t.oid ORDER BY a.attnum;");
        !          4885:        smart_str_0(&querystr);
        !          4886:        
        !          4887:        efree(tmp_name2);
        !          4888:        efree(tmp_name);
        !          4889:        efree(src);     
        !          4890:        
        !          4891:        pg_result = PQexec(pg_link, querystr.c);
        !          4892:        if (PQresultStatus(pg_result) != PGRES_TUPLES_OK || (num_rows = PQntuples(pg_result)) == 0) {
        !          4893:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Table '%s' doesn't exists", table_name);
        !          4894:                smart_str_free(&querystr);
        !          4895:                PQclear(pg_result);
        !          4896:                return FAILURE;
        !          4897:        }
        !          4898:        smart_str_free(&querystr);
        !          4899: 
        !          4900:        for (i = 0; i < num_rows; i++) {
        !          4901:                char *name;
        !          4902:                MAKE_STD_ZVAL(elem);
        !          4903:                array_init(elem);
        !          4904:                add_assoc_long(elem, "num", atoi(PQgetvalue(pg_result,i,1)));
        !          4905:                add_assoc_string(elem, "type", PQgetvalue(pg_result,i,2), 1);
        !          4906:                add_assoc_long(elem, "len", atoi(PQgetvalue(pg_result,i,3)));
        !          4907:                if (!strcmp(PQgetvalue(pg_result,i,4), "t")) {
        !          4908:                        add_assoc_bool(elem, "not null", 1);
        !          4909:                }
        !          4910:                else {
        !          4911:                        add_assoc_bool(elem, "not null", 0);
        !          4912:                }
        !          4913:                if (!strcmp(PQgetvalue(pg_result,i,5), "t")) {
        !          4914:                        add_assoc_bool(elem, "has default", 1);
        !          4915:                }
        !          4916:                else {
        !          4917:                        add_assoc_bool(elem, "has default", 0);
        !          4918:                }
        !          4919:                add_assoc_long(elem, "array dims", atoi(PQgetvalue(pg_result,i,6)));
        !          4920:                name = PQgetvalue(pg_result,i,0);
        !          4921:                add_assoc_zval(meta, name, elem);
        !          4922:        }
        !          4923:        PQclear(pg_result);
        !          4924:        
        !          4925:        return SUCCESS;
        !          4926: }
        !          4927: 
        !          4928: /* }}} */
        !          4929: 
        !          4930: 
        !          4931: /* {{{ proto array pg_meta_data(resource db, string table)
        !          4932:    Get meta_data */
        !          4933: PHP_FUNCTION(pg_meta_data)
        !          4934: {
        !          4935:        zval *pgsql_link;
        !          4936:        char *table_name;
        !          4937:        uint table_name_len;
        !          4938:        PGconn *pgsql;
        !          4939:        int id = -1;
        !          4940:        
        !          4941:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs",
        !          4942:                                                          &pgsql_link, &table_name, &table_name_len) == FAILURE) {
        !          4943:                return;
        !          4944:        }
        !          4945: 
        !          4946:        ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          4947:        
        !          4948:        array_init(return_value);
        !          4949:        if (php_pgsql_meta_data(pgsql, table_name, return_value TSRMLS_CC) == FAILURE) {
        !          4950:                zval_dtor(return_value); /* destroy array */
        !          4951:                RETURN_FALSE;
        !          4952:        }
        !          4953: } 
        !          4954: /* }}} */
        !          4955: 
        !          4956: /* {{{ php_pgsql_get_data_type
        !          4957:  */
        !          4958: static php_pgsql_data_type php_pgsql_get_data_type(const char *type_name, size_t len)
        !          4959: {
        !          4960:     /* This is stupid way to do. I'll fix it when I decied how to support
        !          4961:           user defined types. (Yasuo) */
        !          4962:        
        !          4963:        /* boolean */
        !          4964:        if (!strcmp(type_name, "bool")|| !strcmp(type_name, "boolean"))
        !          4965:                return PG_BOOL;
        !          4966:        /* object id */
        !          4967:        if (!strcmp(type_name, "oid"))
        !          4968:                return PG_OID;
        !          4969:        /* integer */
        !          4970:        if (!strcmp(type_name, "int2") || !strcmp(type_name, "smallint"))
        !          4971:                return PG_INT2;
        !          4972:        if (!strcmp(type_name, "int4") || !strcmp(type_name, "integer"))
        !          4973:                return PG_INT4;
        !          4974:        if (!strcmp(type_name, "int8") || !strcmp(type_name, "bigint"))
        !          4975:                return PG_INT8;
        !          4976:        /* real and other */
        !          4977:        if (!strcmp(type_name, "float4") || !strcmp(type_name, "real"))
        !          4978:                return PG_FLOAT4;
        !          4979:        if (!strcmp(type_name, "float8") || !strcmp(type_name, "double precision"))
        !          4980:                return PG_FLOAT8;
        !          4981:        if (!strcmp(type_name, "numeric"))
        !          4982:                return PG_NUMERIC;
        !          4983:        if (!strcmp(type_name, "money"))
        !          4984:                return PG_MONEY;
        !          4985:        /* character */
        !          4986:        if (!strcmp(type_name, "text"))
        !          4987:                return PG_TEXT;
        !          4988:        if (!strcmp(type_name, "bpchar") || !strcmp(type_name, "character"))
        !          4989:                return PG_CHAR;
        !          4990:        if (!strcmp(type_name, "varchar") || !strcmp(type_name, "character varying"))
        !          4991:                return PG_VARCHAR;
        !          4992:        /* time and interval */
        !          4993:        if (!strcmp(type_name, "abstime"))
        !          4994:                return PG_UNIX_TIME;
        !          4995:        if (!strcmp(type_name, "reltime"))
        !          4996:                return PG_UNIX_TIME_INTERVAL;
        !          4997:        if (!strcmp(type_name, "tinterval"))
        !          4998:                return PG_UNIX_TIME_INTERVAL;
        !          4999:        if (!strcmp(type_name, "date"))
        !          5000:                return PG_DATE;
        !          5001:        if (!strcmp(type_name, "time"))
        !          5002:                return PG_TIME;
        !          5003:        if (!strcmp(type_name, "time with time zone") || !strcmp(type_name, "timetz"))
        !          5004:                return PG_TIME_WITH_TIMEZONE;
        !          5005:        if (!strcmp(type_name, "timestamp without time zone") || !strcmp(type_name, "timestamp"))
        !          5006:                return PG_TIMESTAMP;
        !          5007:        if (!strcmp(type_name, "timestamp with time zone") || !strcmp(type_name, "timestamptz"))
        !          5008:                return PG_TIMESTAMP_WITH_TIMEZONE;
        !          5009:        if (!strcmp(type_name, "interval"))
        !          5010:                return PG_INTERVAL;
        !          5011:        /* binary */
        !          5012:        if (!strcmp(type_name, "bytea"))
        !          5013:                return PG_BYTEA;
        !          5014:        /* network */
        !          5015:        if (!strcmp(type_name, "cidr"))
        !          5016:                return PG_CIDR;
        !          5017:        if (!strcmp(type_name, "inet"))
        !          5018:                return PG_INET;
        !          5019:        if (!strcmp(type_name, "macaddr"))
        !          5020:                return PG_MACADDR;
        !          5021:        /* bit */
        !          5022:        if (!strcmp(type_name, "bit"))
        !          5023:                return PG_BIT;
        !          5024:        if (!strcmp(type_name, "bit varying"))
        !          5025:                return PG_VARBIT;
        !          5026:        /* geometric */
        !          5027:        if (!strcmp(type_name, "line"))
        !          5028:                return PG_LINE;
        !          5029:        if (!strcmp(type_name, "lseg"))
        !          5030:                return PG_LSEG;
        !          5031:        if (!strcmp(type_name, "box"))
        !          5032:                return PG_BOX;
        !          5033:        if (!strcmp(type_name, "path"))
        !          5034:                return PG_PATH;
        !          5035:        if (!strcmp(type_name, "point"))
        !          5036:                return PG_POINT;
        !          5037:        if (!strcmp(type_name, "polygon"))
        !          5038:                return PG_POLYGON;
        !          5039:        if (!strcmp(type_name, "circle"))
        !          5040:                return PG_CIRCLE;
        !          5041:                
        !          5042:        return PG_UNKNOWN;
        !          5043: }
        !          5044: /* }}} */
        !          5045: 
        !          5046: /* {{{ php_pgsql_convert_match
        !          5047:  * test field value with regular expression specified.  
        !          5048:  */
        !          5049: static int php_pgsql_convert_match(const char *str, const char *regex , int icase TSRMLS_DC)
        !          5050: {
        !          5051:        regex_t re;     
        !          5052:        regmatch_t *subs;
        !          5053:        int regopt = REG_EXTENDED;
        !          5054:        int regerr, ret = SUCCESS;
        !          5055: 
        !          5056:        if (icase) {
        !          5057:                regopt |= REG_ICASE;
        !          5058:        }
        !          5059:        
        !          5060:        regerr = regcomp(&re, regex, regopt);
        !          5061:        if (regerr) {
        !          5062:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot compile regex");
        !          5063:                regfree(&re);
        !          5064:                return FAILURE;
        !          5065:        }
        !          5066:        subs = (regmatch_t *)ecalloc(sizeof(regmatch_t), re.re_nsub+1);
        !          5067: 
        !          5068:        regerr = regexec(&re, str, re.re_nsub+1, subs, 0);
        !          5069:        if (regerr == REG_NOMATCH) {
        !          5070: #ifdef PHP_DEBUG               
        !          5071:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "'%s' does not match with '%s'", str, regex);
        !          5072: #endif
        !          5073:                ret = FAILURE;
        !          5074:        }
        !          5075:        else if (regerr) {
        !          5076:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot exec regex");
        !          5077:                ret = FAILURE;
        !          5078:        }
        !          5079:        regfree(&re);
        !          5080:        efree(subs);
        !          5081:        return ret;
        !          5082: }
        !          5083: 
        !          5084: /* }}} */
        !          5085: 
        !          5086: /* {{{ php_pgsql_add_quote
        !          5087:  * add quotes around string.
        !          5088:  */
        !          5089: static int php_pgsql_add_quotes(zval *src, zend_bool should_free TSRMLS_DC) 
        !          5090: {
        !          5091:        smart_str str = {0};
        !          5092:        
        !          5093:        assert(Z_TYPE_P(src) == IS_STRING);
        !          5094:        assert(should_free == 1 || should_free == 0);
        !          5095: 
        !          5096:        smart_str_appendc(&str, '\'');
        !          5097:        smart_str_appendl(&str, Z_STRVAL_P(src), Z_STRLEN_P(src));
        !          5098:        smart_str_appendc(&str, '\'');
        !          5099:        smart_str_0(&str);
        !          5100:        
        !          5101:        if (should_free) {
        !          5102:                efree(Z_STRVAL_P(src));
        !          5103:        }
        !          5104:        Z_STRVAL_P(src) = str.c;
        !          5105:        Z_STRLEN_P(src) = str.len;
        !          5106: 
        !          5107:        return SUCCESS;
        !          5108: }
        !          5109: /* }}} */
        !          5110: 
        !          5111: #define PGSQL_CONV_CHECK_IGNORE() \
        !          5112:                                if (!err && Z_TYPE_P(new_val) == IS_STRING && !strcmp(Z_STRVAL_P(new_val), "NULL")) { \
        !          5113:                                        /* if new_value is string "NULL" and field has default value, remove element to use default value */ \
        !          5114:                                        if (!(opt & PGSQL_CONV_IGNORE_DEFAULT) && Z_BVAL_PP(has_default)) { \
        !          5115:                                                zval_dtor(new_val); \
        !          5116:                                                FREE_ZVAL(new_val); \
        !          5117:                                                skip_field = 1; \
        !          5118:                                        } \
        !          5119:                                        /* raise error if it's not null and cannot be ignored */ \
        !          5120:                                        else if (!(opt & PGSQL_CONV_IGNORE_NOT_NULL) && Z_BVAL_PP(not_null)) { \
        !          5121:                                                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected NULL for 'NOT NULL' field '%s'", field ); \
        !          5122:                                                err = 1; \
        !          5123:                                        } \
        !          5124:                                }               
        !          5125: 
        !          5126: /* {{{ php_pgsql_convert
        !          5127:  * check and convert array values (fieldname=>vlaue pair) for sql
        !          5128:  */
        !          5129: PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, const zval *values, zval *result, ulong opt TSRMLS_DC) 
        !          5130: {
        !          5131:        HashPosition pos;
        !          5132:        char *field = NULL;
        !          5133:        uint field_len = -1;
        !          5134:        ulong num_idx = -1;
        !          5135:        zval *meta, **def, **type, **not_null, **has_default, **val, *new_val;
        !          5136:        int new_len, key_type, err = 0, skip_field;
        !          5137:        
        !          5138:        assert(pg_link != NULL);
        !          5139:        assert(Z_TYPE_P(values) == IS_ARRAY);
        !          5140:        assert(Z_TYPE_P(result) == IS_ARRAY);
        !          5141:        assert(!(opt & ~PGSQL_CONV_OPTS));
        !          5142: 
        !          5143:        if (!table_name) {
        !          5144:                return FAILURE;
        !          5145:        }
        !          5146:        MAKE_STD_ZVAL(meta);
        !          5147:        array_init(meta);
        !          5148:        if (php_pgsql_meta_data(pg_link, table_name, meta TSRMLS_CC) == FAILURE) {
        !          5149:                zval_dtor(meta);
        !          5150:                FREE_ZVAL(meta);
        !          5151:                return FAILURE;
        !          5152:        }
        !          5153:        for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos);
        !          5154:                 zend_hash_get_current_data_ex(Z_ARRVAL_P(values), (void **)&val, &pos) == SUCCESS;
        !          5155:                 zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos)) {
        !          5156:                skip_field = 0;
        !          5157:                new_val = NULL;
        !          5158:                
        !          5159:                if ((key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(values), &field, &field_len, &num_idx, 0, &pos)) == HASH_KEY_NON_EXISTANT) {
        !          5160:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to get array key type");
        !          5161:                        err = 1;
        !          5162:                }
        !          5163:                if (!err && key_type == HASH_KEY_IS_LONG) {
        !          5164:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Accepts only string key for values");
        !          5165:                        err = 1;
        !          5166:                }
        !          5167:                if (!err && key_type == HASH_KEY_NON_EXISTANT) {
        !          5168:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Accepts only string key for values");
        !          5169:                        err = 1;
        !          5170:                }
        !          5171:                if (!err && zend_hash_find(Z_ARRVAL_P(meta), field, field_len, (void **)&def) == FAILURE) {
        !          5172:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid field name (%s) in values", field);
        !          5173:                        err = 1;
        !          5174:                }
        !          5175:                if (!err && zend_hash_find(Z_ARRVAL_PP(def), "type", sizeof("type"), (void **)&type) == FAILURE) {
        !          5176:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected broken meta data. Missing 'type'");
        !          5177:                        err = 1;
        !          5178:                }
        !          5179:                if (!err && zend_hash_find(Z_ARRVAL_PP(def), "not null", sizeof("not null"), (void **)&not_null) == FAILURE) {
        !          5180:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected broken meta data. Missing 'not null'");
        !          5181:                        err = 1;
        !          5182:                }
        !          5183:                if (!err && zend_hash_find(Z_ARRVAL_PP(def), "has default", sizeof("has default"), (void **)&has_default) == FAILURE) {
        !          5184:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected broken meta data. Missing 'has default'");
        !          5185:                        err = 1;
        !          5186:                }
        !          5187:                if (!err && (Z_TYPE_PP(val) == IS_ARRAY ||
        !          5188:                         Z_TYPE_PP(val) == IS_OBJECT ||
        !          5189:                         Z_TYPE_PP(val) == IS_CONSTANT_ARRAY)) {
        !          5190:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects scaler values as field values");
        !          5191:                        err = 1;
        !          5192:                }
        !          5193:                if (err) {
        !          5194:                        break; /* break out for() */
        !          5195:                }
        !          5196:                ALLOC_INIT_ZVAL(new_val);
        !          5197:                switch(php_pgsql_get_data_type(Z_STRVAL_PP(type), Z_STRLEN_PP(type)))
        !          5198:                {
        !          5199:                        case PG_BOOL:
        !          5200:                                switch (Z_TYPE_PP(val)) {
        !          5201:                                        case IS_STRING:
        !          5202:                                                if (Z_STRLEN_PP(val) == 0) {
        !          5203:                                                        ZVAL_STRING(new_val, "NULL", 1);
        !          5204:                                                }
        !          5205:                                                else {
        !          5206:                                                        if (!strcmp(Z_STRVAL_PP(val), "t") || !strcmp(Z_STRVAL_PP(val), "T") ||
        !          5207:                                                                !strcmp(Z_STRVAL_PP(val), "y") || !strcmp(Z_STRVAL_PP(val), "Y") ||
        !          5208:                                                                !strcmp(Z_STRVAL_PP(val), "true") || !strcmp(Z_STRVAL_PP(val), "True") ||
        !          5209:                                                                !strcmp(Z_STRVAL_PP(val), "yes") || !strcmp(Z_STRVAL_PP(val), "Yes") ||
        !          5210:                                                                !strcmp(Z_STRVAL_PP(val), "1")) {
        !          5211:                                                                ZVAL_STRING(new_val, "'t'", 1);
        !          5212:                                                        }
        !          5213:                                                        else if (!strcmp(Z_STRVAL_PP(val), "f") || !strcmp(Z_STRVAL_PP(val), "F") ||
        !          5214:                                                                         !strcmp(Z_STRVAL_PP(val), "n") || !strcmp(Z_STRVAL_PP(val), "N") ||
        !          5215:                                                                         !strcmp(Z_STRVAL_PP(val), "false") ||  !strcmp(Z_STRVAL_PP(val), "False") ||
        !          5216:                                                                         !strcmp(Z_STRVAL_PP(val), "no") ||  !strcmp(Z_STRVAL_PP(val), "No") ||
        !          5217:                                                                         !strcmp(Z_STRVAL_PP(val), "0")) {
        !          5218:                                                                ZVAL_STRING(new_val, "'f'", 1);
        !          5219:                                                        }
        !          5220:                                                        else {
        !          5221:                                                                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected invalid value (%s) for PostgreSQL %s field (%s)", Z_STRVAL_PP(val), Z_STRVAL_PP(type), field);
        !          5222:                                                                err = 1;
        !          5223:                                                        }
        !          5224:                                                }
        !          5225:                                                break;
        !          5226:                                                
        !          5227:                                        case IS_LONG:
        !          5228:                                        case IS_BOOL:
        !          5229:                                                if (Z_LVAL_PP(val)) {
        !          5230:                                                        ZVAL_STRING(new_val, "'t'", 1);
        !          5231:                                                }
        !          5232:                                                else {
        !          5233:                                                        ZVAL_STRING(new_val, "'f'", 1);
        !          5234:                                                }
        !          5235:                                                break;
        !          5236: 
        !          5237:                                        case IS_NULL:
        !          5238:                                                ZVAL_STRING(new_val, "NULL", 1);
        !          5239:                                                break;
        !          5240: 
        !          5241:                                        default:
        !          5242:                                                err = 1;
        !          5243:                                }
        !          5244:                                PGSQL_CONV_CHECK_IGNORE();
        !          5245:                                if (err) {
        !          5246:                                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects string, null, long or boolelan value for PostgreSQL '%s' (%s)", Z_STRVAL_PP(type), field);
        !          5247:                                }
        !          5248:                                break;
        !          5249:                                        
        !          5250:                        case PG_OID:
        !          5251:                        case PG_INT2:
        !          5252:                        case PG_INT4:
        !          5253:                        case PG_INT8:
        !          5254:                                switch (Z_TYPE_PP(val)) {
        !          5255:                                        case IS_STRING:
        !          5256:                                                if (Z_STRLEN_PP(val) == 0) {
        !          5257:                                                        ZVAL_STRING(new_val, "NULL", 1);
        !          5258:                                                }
        !          5259:                                                else {
        !          5260:                                                        /* FIXME: better regex must be used */
        !          5261:                                                        if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^([+-]{0,1}[0-9]+)$", 0 TSRMLS_CC) == FAILURE) {
        !          5262:                                                                err = 1;
        !          5263:                                                        }
        !          5264:                                                        else {
        !          5265:                                                                ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
        !          5266:                                                        }
        !          5267:                                                }
        !          5268:                                                break;
        !          5269:                                                
        !          5270:                                        case IS_DOUBLE:
        !          5271:                                                ZVAL_DOUBLE(new_val, Z_DVAL_PP(val));
        !          5272:                                                convert_to_long_ex(&new_val);
        !          5273:                                                break;
        !          5274:                                                
        !          5275:                                        case IS_LONG:
        !          5276:                                                ZVAL_LONG(new_val, Z_LVAL_PP(val));
        !          5277:                                                break;
        !          5278:                                                
        !          5279:                                        case IS_NULL:
        !          5280:                                                ZVAL_STRING(new_val, "NULL", 1);
        !          5281:                                                break;
        !          5282: 
        !          5283:                                        default:
        !          5284:                                                err = 1;
        !          5285:                                }
        !          5286:                                PGSQL_CONV_CHECK_IGNORE();
        !          5287:                                if (err) {
        !          5288:                                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL, string, long or double value for pgsql '%s' (%s)", Z_STRVAL_PP(type), field);
        !          5289:                                }
        !          5290:                                break;
        !          5291: 
        !          5292:                        case PG_NUMERIC:
        !          5293:                        case PG_MONEY:
        !          5294:                        case PG_FLOAT4:
        !          5295:                        case PG_FLOAT8:
        !          5296:                                switch (Z_TYPE_PP(val)) {
        !          5297:                                        case IS_STRING:
        !          5298:                                                if (Z_STRLEN_PP(val) == 0) {
        !          5299:                                                        ZVAL_STRING(new_val, "NULL", 1);
        !          5300:                                                }
        !          5301:                                                else {
        !          5302:                                                        /* FIXME: better regex must be used */
        !          5303:                                                        if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^([+-]{0,1}[0-9]+)|([+-]{0,1}[0-9]*[\\.][0-9]+)|([+-]{0,1}[0-9]+[\\.][0-9]*)$", 0 TSRMLS_CC) == FAILURE) {
        !          5304:                                                                err = 1;
        !          5305:                                                        }
        !          5306:                                                        else {
        !          5307:                                                                ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
        !          5308:                                                        }
        !          5309:                                                }
        !          5310:                                                break;
        !          5311:                                                
        !          5312:                                        case IS_LONG:
        !          5313:                                                ZVAL_LONG(new_val, Z_LVAL_PP(val));
        !          5314:                                                break;
        !          5315:                                                
        !          5316:                                        case IS_DOUBLE:
        !          5317:                                                ZVAL_DOUBLE(new_val, Z_DVAL_PP(val));
        !          5318:                                                break;
        !          5319:                                                
        !          5320:                                        case IS_NULL:
        !          5321:                                                ZVAL_STRING(new_val, "NULL", 1);
        !          5322:                                                break;
        !          5323: 
        !          5324:                                        default:
        !          5325:                                                err = 1;
        !          5326:                                }
        !          5327:                                PGSQL_CONV_CHECK_IGNORE();
        !          5328:                                if (err) {
        !          5329:                                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL, string, long or double value for PostgreSQL '%s' (%s)", Z_STRVAL_PP(type), field);
        !          5330:                                }
        !          5331:                                break;
        !          5332: 
        !          5333:                        case PG_TEXT:
        !          5334:                        case PG_CHAR:
        !          5335:                        case PG_VARCHAR:
        !          5336:                                switch (Z_TYPE_PP(val)) {
        !          5337:                                        case IS_STRING:
        !          5338:                                                if (Z_STRLEN_PP(val) == 0) {
        !          5339:                                                        if (opt & PGSQL_CONV_FORCE_NULL) {
        !          5340:                                                                ZVAL_STRING(new_val, "NULL", 1);
        !          5341:                                                        } else {
        !          5342:                                                                ZVAL_STRING(new_val, "''", 1);
        !          5343:                                                        }
        !          5344:                                                }
        !          5345:                                                else {
        !          5346:                                                        Z_TYPE_P(new_val) = IS_STRING;
        !          5347: #if HAVE_PQESCAPE
        !          5348:                                                        {
        !          5349:                                                                char *tmp;
        !          5350:                                                                tmp = (char *)safe_emalloc(Z_STRLEN_PP(val), 2, 1);
        !          5351:                                                                Z_STRLEN_P(new_val) = (int)PQescapeString(tmp, Z_STRVAL_PP(val), Z_STRLEN_PP(val));
        !          5352:                                                                Z_STRVAL_P(new_val) = tmp;
        !          5353:                                                        }
        !          5354: #else                                  
        !          5355:                                                        Z_STRVAL_P(new_val) = php_addslashes(Z_STRVAL_PP(val), Z_STRLEN_PP(val), &Z_STRLEN_P(new_val), 0 TSRMLS_CC);
        !          5356: #endif
        !          5357:                                                        php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
        !          5358:                                                }
        !          5359:                                                break;
        !          5360:                                                
        !          5361:                                        case IS_LONG:
        !          5362:                                                ZVAL_LONG(new_val, Z_LVAL_PP(val));
        !          5363:                                                convert_to_string_ex(&new_val);
        !          5364:                                                break;
        !          5365:                                                
        !          5366:                                        case IS_DOUBLE:
        !          5367:                                                ZVAL_DOUBLE(new_val, Z_DVAL_PP(val));
        !          5368:                                                convert_to_string_ex(&new_val);
        !          5369:                                                break;
        !          5370: 
        !          5371:                                        case IS_NULL:
        !          5372:                                                ZVAL_STRING(new_val, "NULL", 1);
        !          5373:                                                break;
        !          5374: 
        !          5375:                                        default:
        !          5376:                                                err = 1;
        !          5377:                                }
        !          5378:                                PGSQL_CONV_CHECK_IGNORE();
        !          5379:                                if (err) {
        !          5380:                                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL, string, long or double value for PostgreSQL '%s' (%s)", Z_STRVAL_PP(type), field);
        !          5381:                                }
        !          5382:                                break;
        !          5383:                                        
        !          5384:                        case PG_UNIX_TIME:
        !          5385:                        case PG_UNIX_TIME_INTERVAL:
        !          5386:                                /* these are the actallay a integer */
        !          5387:                                switch (Z_TYPE_PP(val)) {
        !          5388:                                        case IS_STRING:
        !          5389:                                                if (Z_STRLEN_PP(val) == 0) {
        !          5390:                                                        ZVAL_STRING(new_val, "NULL", 1);
        !          5391:                                                }
        !          5392:                                                else {
        !          5393:                                                        /* FIXME: Better regex must be used */
        !          5394:                                                        if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^[0-9]+$", 0 TSRMLS_CC) == FAILURE) {
        !          5395:                                                                err = 1;
        !          5396:                                                        } 
        !          5397:                                                        else {
        !          5398:                                                                ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
        !          5399:                                                                convert_to_long_ex(&new_val);
        !          5400:                                                        }
        !          5401:                                                }
        !          5402:                                                break;
        !          5403:                                                
        !          5404:                                        case IS_DOUBLE:
        !          5405:                                                ZVAL_DOUBLE(new_val, Z_DVAL_PP(val));
        !          5406:                                                convert_to_long_ex(&new_val);
        !          5407:                                                break;
        !          5408:                                                
        !          5409:                                        case IS_LONG:
        !          5410:                                                ZVAL_LONG(new_val, Z_LVAL_PP(val));
        !          5411:                                                break;
        !          5412:                                                
        !          5413:                                        case IS_NULL:
        !          5414:                                                ZVAL_STRING(new_val, "NULL", 1);
        !          5415:                                                break;
        !          5416: 
        !          5417:                                        default:
        !          5418:                                                err = 1;
        !          5419:                                }
        !          5420:                                PGSQL_CONV_CHECK_IGNORE();
        !          5421:                                if (err) {
        !          5422:                                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL, string, long or double value for '%s' (%s)", Z_STRVAL_PP(type), field);
        !          5423:                                }
        !          5424:                                break;
        !          5425:                                
        !          5426:                        case PG_CIDR:
        !          5427:                        case PG_INET:
        !          5428:                                switch (Z_TYPE_PP(val)) {
        !          5429:                                        case IS_STRING:
        !          5430:                                                if (Z_STRLEN_PP(val) == 0) {
        !          5431:                                                        ZVAL_STRING(new_val, "NULL", 1);
        !          5432:                                                }
        !          5433:                                                else {
        !          5434:                                                        /* FIXME: Better regex must be used */
        !          5435:                                                        if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^([0-9]{1,3}\\.){3}[0-9]{1,3}(/[0-9]{1,2}){0,1}$", 0 TSRMLS_CC) == FAILURE) {
        !          5436:                                                                err = 1;
        !          5437:                                                        }
        !          5438:                                                        else {
        !          5439:                                                                ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
        !          5440:                                                                php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
        !          5441:                                                        }
        !          5442:                                                }
        !          5443:                                                break;
        !          5444:                                                
        !          5445:                                        case IS_NULL:
        !          5446:                                                ZVAL_STRING(new_val, "NULL", 1);
        !          5447:                                                break;
        !          5448: 
        !          5449:                                        default:
        !          5450:                                                err = 1;
        !          5451:                                }                               
        !          5452:                                PGSQL_CONV_CHECK_IGNORE();
        !          5453:                                if (err) {
        !          5454:                                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL or string for '%s' (%s)", Z_STRVAL_PP(type), field);
        !          5455:                                }
        !          5456:                                break;
        !          5457:                                
        !          5458:                        case PG_TIME_WITH_TIMEZONE:
        !          5459:                        case PG_TIMESTAMP:
        !          5460:                        case PG_TIMESTAMP_WITH_TIMEZONE:
        !          5461:                                switch(Z_TYPE_PP(val)) {
        !          5462:                                        case IS_STRING:
        !          5463:                                                if (Z_STRLEN_PP(val) == 0) {
        !          5464:                                                        ZVAL_STRINGL(new_val, "NULL", sizeof("NULL")-1, 1);
        !          5465:                                                } else if (!strcasecmp(Z_STRVAL_PP(val), "now()")) {
        !          5466:                                                        ZVAL_STRINGL(new_val, "NOW()", sizeof("NOW()")-1, 1);
        !          5467:                                                } else {
        !          5468:                                                        /* FIXME: better regex must be used */
        !          5469:                                                        if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^([0-9]{4}[/-][0-9]{1,2}[/-][0-9]{1,2})([ \\t]+(([0-9]{1,2}:[0-9]{1,2}){1}(:[0-9]{1,2}){0,1}(\\.[0-9]+){0,1}([ \\t]*([+-][0-9]{1,4}(:[0-9]{1,2}){0,1}|[-a-zA-Z_/+]{1,50})){0,1})){0,1}$", 1 TSRMLS_CC) == FAILURE) {
        !          5470:                                                                err = 1;
        !          5471:                                                        } else {
        !          5472:                                                                ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
        !          5473:                                                                php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
        !          5474:                                                        }
        !          5475:                                                }
        !          5476:                                                break;
        !          5477:                                
        !          5478:                                        case IS_NULL:
        !          5479:                                                ZVAL_STRINGL(new_val, "NULL", sizeof("NULL")-1, 1);
        !          5480:                                                break;
        !          5481: 
        !          5482:                                        default:
        !          5483:                                                err = 1;
        !          5484:                                }
        !          5485:                                PGSQL_CONV_CHECK_IGNORE();
        !          5486:                                if (err) {
        !          5487:                                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL or string for PostgreSQL %s field (%s)", Z_STRVAL_PP(type), field);
        !          5488:                                }
        !          5489:                                break;
        !          5490:                                
        !          5491:                        case PG_DATE:
        !          5492:                                switch(Z_TYPE_PP(val)) {
        !          5493:                                        case IS_STRING:
        !          5494:                                                if (Z_STRLEN_PP(val) == 0) {
        !          5495:                                                        ZVAL_STRING(new_val, "NULL", 1);
        !          5496:                                                }
        !          5497:                                                else {
        !          5498:                                                        /* FIXME: better regex must be used */
        !          5499:                                                        if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^([0-9]{4}[/-][0-9]{1,2}[/-][0-9]{1,2})$", 1 TSRMLS_CC) == FAILURE) {
        !          5500:                                                                err = 1;
        !          5501:                                                        }
        !          5502:                                                        else {
        !          5503:                                                                ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
        !          5504:                                                                php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
        !          5505:                                                        }
        !          5506:                                                }
        !          5507:                                                break;
        !          5508:                                
        !          5509:                                        case IS_NULL:
        !          5510:                                                ZVAL_STRING(new_val, "NULL", 1);
        !          5511:                                                break;
        !          5512: 
        !          5513:                                        default:
        !          5514:                                                err = 1;
        !          5515:                                }
        !          5516:                                PGSQL_CONV_CHECK_IGNORE();
        !          5517:                                if (err) {
        !          5518:                                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL or string for PostgreSQL %s field (%s)", Z_STRVAL_PP(type), field);
        !          5519:                                }
        !          5520:                                break;
        !          5521: 
        !          5522:                        case PG_TIME:
        !          5523:                                switch(Z_TYPE_PP(val)) {
        !          5524:                                        case IS_STRING:
        !          5525:                                                if (Z_STRLEN_PP(val) == 0) {
        !          5526:                                                        ZVAL_STRING(new_val, "NULL", 1);
        !          5527:                                                }
        !          5528:                                                else {
        !          5529:                                                        /* FIXME: better regex must be used */
        !          5530:                                                        if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^(([0-9]{1,2}:[0-9]{1,2}){1}(:[0-9]{1,2}){0,1})){0,1}$", 1 TSRMLS_CC) == FAILURE) {
        !          5531:                                                                err = 1;
        !          5532:                                                        }
        !          5533:                                                        else {
        !          5534:                                                                ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
        !          5535:                                                                php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
        !          5536:                                                        }
        !          5537:                                                }
        !          5538:                                                break;
        !          5539:                                
        !          5540:                                        case IS_NULL:
        !          5541:                                                ZVAL_STRING(new_val, "NULL", 1);
        !          5542:                                                break;
        !          5543: 
        !          5544:                                        default:
        !          5545:                                                err = 1;
        !          5546:                                }
        !          5547:                                PGSQL_CONV_CHECK_IGNORE();
        !          5548:                                if (err) {
        !          5549:                                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL or string for PostgreSQL %s field (%s)", Z_STRVAL_PP(type), field);
        !          5550:                                }
        !          5551:                                break;
        !          5552: 
        !          5553:                        case PG_INTERVAL:
        !          5554:                                switch(Z_TYPE_PP(val)) {
        !          5555:                                        case IS_STRING:
        !          5556:                                                if (Z_STRLEN_PP(val) == 0) {
        !          5557:                                                        ZVAL_STRING(new_val, "NULL", 1);
        !          5558:                                                }
        !          5559:                                                else {
        !          5560: 
        !          5561:                                                        /* From the Postgres docs:
        !          5562: 
        !          5563:                                                           interval values can be written with the following syntax:
        !          5564:                                                           [@] quantity unit [quantity unit...] [direction]
        !          5565:                                                           
        !          5566:                                                           Where: quantity is a number (possibly signed); unit is second, minute, hour,
        !          5567:                                                           day, week, month, year, decade, century, millennium, or abbreviations or
        !          5568:                                                           plurals of these units [note not *all* abbreviations] ; direction can be
        !          5569:                                                           ago or empty. The at sign (@) is optional noise.
        !          5570:                                                           
        !          5571:                                                           ...
        !          5572:                                                           
        !          5573:                                                           Quantities of days, hours, minutes, and seconds can be specified without explicit
        !          5574:                                                           unit markings. For example, '1 12:59:10' is read the same as '1 day 12 hours 59 min 10
        !          5575:                                                           sec'.
        !          5576:                                                        */                                                        
        !          5577:                                                        if (php_pgsql_convert_match(Z_STRVAL_PP(val),
        !          5578:                                                                                                                "^(@?[ \\t]+)?("
        !          5579:                                                                                                                
        !          5580:                                                                                                                /* Textual time units and their abbreviations: */
        !          5581:                                                                                                                "(([-+]?[ \\t]+)?"
        !          5582:                                                                                                                "[0-9]+(\\.[0-9]*)?[ \\t]*"
        !          5583:                                                                                                                "(millenniums|millennia|millennium|mil|mils|"
        !          5584:                                                                                                                "centuries|century|cent|c|"
        !          5585:                                                                                                                "decades|decade|dec|decs|"
        !          5586:                                                                                                                "years|year|y|"
        !          5587:                                                                                                                "months|month|mon|"
        !          5588:                                                                                                                "weeks|week|w|" 
        !          5589:                                                                                                                "days|day|d|"
        !          5590:                                                                                                                "hours|hour|hr|hrs|h|"
        !          5591:                                                                                                                "minutes|minute|mins|min|m|"
        !          5592:                                                                                                                "seconds|second|secs|sec|s))+|"
        !          5593: 
        !          5594:                                                                                                                /* Textual time units plus (dd)* hh[:mm[:ss]] */
        !          5595:                                                                                                                "((([-+]?[ \\t]+)?"
        !          5596:                                                                                                                "[0-9]+(\\.[0-9]*)?[ \\t]*"
        !          5597:                                                                                                                "(millenniums|millennia|millennium|mil|mils|"
        !          5598:                                                                                                                "centuries|century|cent|c|"
        !          5599:                                                                                                                "decades|decade|dec|decs|"
        !          5600:                                                                                                                "years|year|y|"
        !          5601:                                                                                                                "months|month|mon|"
        !          5602:                                                                                                                "weeks|week|w|"
        !          5603:                                                                                                                "days|day|d))+" 
        !          5604:                                                                                                                "([-+]?[ \\t]+"
        !          5605:                                                                                                                "([0-9]+[ \\t]+)+"                               /* dd */
        !          5606:                                                                                                                "(([0-9]{1,2}:){0,2}[0-9]{0,2})" /* hh:[mm:[ss]] */
        !          5607:                                                                                                                ")?))"
        !          5608:                                                                                                                "([ \\t]+ago)?$",
        !          5609:                                                                                                                1 TSRMLS_CC) == FAILURE) {
        !          5610:                                                                err = 1;
        !          5611:                                                        }
        !          5612:                                                        else {
        !          5613:                                                                ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
        !          5614:                                                                php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
        !          5615:                                                        }
        !          5616:                                                }       
        !          5617:                                                break;
        !          5618:                                
        !          5619:                                        case IS_NULL:
        !          5620:                                                ZVAL_STRING(new_val, "NULL", 1);
        !          5621:                                                break;
        !          5622: 
        !          5623:                                        default:
        !          5624:                                                err = 1;
        !          5625:                                }
        !          5626:                                PGSQL_CONV_CHECK_IGNORE();
        !          5627:                                if (err) {
        !          5628:                                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL or string for PostgreSQL %s field (%s)", Z_STRVAL_PP(type), field);
        !          5629:                                }
        !          5630:                                break;
        !          5631: #ifdef HAVE_PQESCAPE
        !          5632:                        case PG_BYTEA:
        !          5633:                                switch (Z_TYPE_PP(val)) {
        !          5634:                                        case IS_STRING:
        !          5635:                                                if (Z_STRLEN_PP(val) == 0) {
        !          5636:                                                        ZVAL_STRING(new_val, "NULL", 1);
        !          5637:                                                }
        !          5638:                                                else {
        !          5639:                                                        unsigned char *tmp;
        !          5640:                                                        size_t to_len;
        !          5641: #ifdef HAVE_PQESCAPE_BYTEA_CONN
        !          5642:                                                        tmp = PQescapeByteaConn(pg_link, Z_STRVAL_PP(val), Z_STRLEN_PP(val), &to_len);
        !          5643: #else
        !          5644:                                                        tmp = PQescapeBytea(Z_STRVAL_PP(val), Z_STRLEN_PP(val), &to_len);
        !          5645: #endif
        !          5646:                                                        Z_TYPE_P(new_val) = IS_STRING;
        !          5647:                                                        Z_STRLEN_P(new_val) = to_len-1; /* PQescapeBytea's to_len includes additional '\0' */
        !          5648:                                                        Z_STRVAL_P(new_val) = emalloc(to_len);
        !          5649:                                                        memcpy(Z_STRVAL_P(new_val), tmp, to_len);
        !          5650:                                                        PQfreemem(tmp);
        !          5651:                                                        php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
        !          5652:                                                                
        !          5653:                                                }
        !          5654:                                                break;
        !          5655:                                                
        !          5656:                                        case IS_LONG:
        !          5657:                                                ZVAL_LONG(new_val, Z_LVAL_PP(val));
        !          5658:                                                convert_to_string_ex(&new_val);
        !          5659:                                                break;
        !          5660:                                                
        !          5661:                                        case IS_DOUBLE:
        !          5662:                                                ZVAL_DOUBLE(new_val, Z_DVAL_PP(val));
        !          5663:                                                convert_to_string_ex(&new_val);
        !          5664:                                                break;
        !          5665: 
        !          5666:                                        case IS_NULL:
        !          5667:                                                ZVAL_STRING(new_val, "NULL", 1);
        !          5668:                                                break;
        !          5669: 
        !          5670:                                        default:
        !          5671:                                                err = 1;
        !          5672:                                }
        !          5673:                                PGSQL_CONV_CHECK_IGNORE();
        !          5674:                                if (err) {
        !          5675:                                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL, string, long or double value for PostgreSQL '%s' (%s)", Z_STRVAL_PP(type), field);
        !          5676:                                }
        !          5677:                                break;
        !          5678:                                
        !          5679: #endif
        !          5680:                        case PG_MACADDR:
        !          5681:                                switch(Z_TYPE_PP(val)) {
        !          5682:                                        case IS_STRING:
        !          5683:                                                if (Z_STRLEN_PP(val) == 0) {
        !          5684:                                                        ZVAL_STRING(new_val, "NULL", 1);
        !          5685:                                                }
        !          5686:                                                else {
        !          5687:                                                        if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^([0-9a-f]{2,2}:){5,5}[0-9a-f]{2,2}$", 1 TSRMLS_CC) == FAILURE) {
        !          5688:                                                                err = 1;
        !          5689:                                                        }
        !          5690:                                                        else {
        !          5691:                                                                ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
        !          5692:                                                                php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
        !          5693:                                                        }
        !          5694:                                                }
        !          5695:                                                break;
        !          5696:                                
        !          5697:                                        case IS_NULL:
        !          5698:                                                ZVAL_STRING(new_val, "NULL", 1);
        !          5699:                                                break;
        !          5700: 
        !          5701:                                        default:
        !          5702:                                                err = 1;
        !          5703:                                }
        !          5704:                                PGSQL_CONV_CHECK_IGNORE();
        !          5705:                                if (err) {
        !          5706:                                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL or string for PostgreSQL %s field (%s)", Z_STRVAL_PP(type), field);
        !          5707:                                }
        !          5708:                                break;
        !          5709: 
        !          5710:                                /* bit */
        !          5711:                        case PG_BIT:
        !          5712:                        case PG_VARBIT:
        !          5713:                                /* geometric */
        !          5714:                        case PG_LINE:
        !          5715:                        case PG_LSEG:
        !          5716:                        case PG_POINT:
        !          5717:                        case PG_BOX:
        !          5718:                        case PG_PATH:
        !          5719:                        case PG_POLYGON:
        !          5720:                        case PG_CIRCLE:
        !          5721:                                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "PostgreSQL '%s' type (%s) is not supported", Z_STRVAL_PP(type), field);
        !          5722:                                err = 1;
        !          5723:                                break;
        !          5724:                                
        !          5725:                        case PG_UNKNOWN:
        !          5726:                        default:
        !          5727:                                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown or system data type '%s' for '%s'", Z_STRVAL_PP(type), field);
        !          5728:                                err = 1;
        !          5729:                                break;
        !          5730:                } /* switch */
        !          5731:                
        !          5732:                if (err) {
        !          5733:                        zval_dtor(new_val);
        !          5734:                        FREE_ZVAL(new_val);
        !          5735:                        break; /* break out for() */
        !          5736:                }
        !          5737:                if (!skip_field) {
        !          5738:                        /* If field is NULL and HAS DEFAULT, should be skipped */
        !          5739:                        field = php_addslashes(field, strlen(field), &new_len, 0 TSRMLS_CC);
        !          5740:                        add_assoc_zval(result, field, new_val);
        !          5741:                        efree(field);
        !          5742:                }
        !          5743:        } /* for */
        !          5744:        zval_dtor(meta);
        !          5745:        FREE_ZVAL(meta);
        !          5746: 
        !          5747:        if (err) {
        !          5748:                /* shouldn't destroy & free zval here */
        !          5749:                return FAILURE;
        !          5750:        }
        !          5751:        return SUCCESS;
        !          5752: }
        !          5753: /* }}} */
        !          5754: 
        !          5755: 
        !          5756: /* {{{ proto array pg_convert(resource db, string table, array values[, int options])
        !          5757:    Check and convert values for PostgreSQL SQL statement */
        !          5758: PHP_FUNCTION(pg_convert)
        !          5759: {
        !          5760:        zval *pgsql_link, *values;
        !          5761:        char *table_name;
        !          5762:        int table_name_len;
        !          5763:        ulong option = 0;
        !          5764:        PGconn *pg_link;
        !          5765:        int id = -1;
        !          5766:        
        !          5767:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
        !          5768:                                                          "rsa|l", &pgsql_link, &table_name, &table_name_len, &values, &option) == FAILURE) {
        !          5769:                return;
        !          5770:        }
        !          5771:        if (option & ~PGSQL_CONV_OPTS) {
        !          5772:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is specified");
        !          5773:                RETURN_FALSE;
        !          5774:        }
        !          5775:        if (!table_name_len) {
        !          5776:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Table name is invalid");
        !          5777:                RETURN_FALSE;
        !          5778:        }
        !          5779: 
        !          5780:        ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          5781: 
        !          5782:        if (php_pgsql_flush_query(pg_link TSRMLS_CC)) {
        !          5783:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected unhandled result(s) in connection");
        !          5784:        }
        !          5785:        array_init(return_value);
        !          5786:        if (php_pgsql_convert(pg_link, table_name, values, return_value, option TSRMLS_CC) == FAILURE) {
        !          5787:                zval_dtor(return_value);
        !          5788:                RETURN_FALSE;
        !          5789:        }
        !          5790: }
        !          5791: /* }}} */
        !          5792: 
        !          5793: static int do_exec(smart_str *querystr, int expect, PGconn *pg_link, ulong opt TSRMLS_DC)
        !          5794: {
        !          5795:        if (opt & PGSQL_DML_ASYNC) {
        !          5796:                if (PQsendQuery(pg_link, querystr->c)) {
        !          5797:                        return 0;
        !          5798:                }
        !          5799:        }
        !          5800:        else {
        !          5801:                PGresult *pg_result;
        !          5802: 
        !          5803:                pg_result = PQexec(pg_link, querystr->c);
        !          5804:                if (PQresultStatus(pg_result) == expect) {
        !          5805:                        PQclear(pg_result);
        !          5806:                        return 0;
        !          5807:                } else {
        !          5808:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", PQresultErrorMessage(pg_result));
        !          5809:                        PQclear(pg_result);
        !          5810:                }
        !          5811:        }
        !          5812: 
        !          5813:        return -1;
        !          5814: }
        !          5815: 
        !          5816: /* {{{ php_pgsql_insert
        !          5817:  */
        !          5818: PHP_PGSQL_API int php_pgsql_insert(PGconn *pg_link, const char *table, zval *var_array, ulong opt, char **sql TSRMLS_DC)
        !          5819: {
        !          5820:        zval **val, *converted = NULL;
        !          5821:        char buf[256];
        !          5822:        char *fld;
        !          5823:        smart_str querystr = {0};
        !          5824:        int key_type, ret = FAILURE;
        !          5825:        uint fld_len;
        !          5826:        ulong num_idx;
        !          5827:        HashPosition pos;
        !          5828: 
        !          5829:        assert(pg_link != NULL);
        !          5830:        assert(table != NULL);
        !          5831:        assert(Z_TYPE_P(var_array) == IS_ARRAY);
        !          5832: 
        !          5833:        if (zend_hash_num_elements(Z_ARRVAL_P(var_array)) == 0) {
        !          5834:                smart_str_appends(&querystr, "INSERT INTO ");
        !          5835:                smart_str_appends(&querystr, table);
        !          5836:                smart_str_appends(&querystr, " DEFAULT VALUES");
        !          5837: 
        !          5838:                goto no_values;
        !          5839:        }
        !          5840: 
        !          5841:        /* convert input array if needed */
        !          5842:        if (!(opt & PGSQL_DML_NO_CONV)) {
        !          5843:                MAKE_STD_ZVAL(converted);
        !          5844:                array_init(converted);
        !          5845:                if (php_pgsql_convert(pg_link, table, var_array, converted, (opt & PGSQL_CONV_OPTS) TSRMLS_CC) == FAILURE) {
        !          5846:                        goto cleanup;
        !          5847:                }
        !          5848:                var_array = converted;
        !          5849:        }
        !          5850:        
        !          5851:        smart_str_appends(&querystr, "INSERT INTO ");
        !          5852:        smart_str_appends(&querystr, table);
        !          5853:        smart_str_appends(&querystr, " (");
        !          5854:        
        !          5855:        zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(var_array), &pos);
        !          5856:        while ((key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(var_array), &fld,
        !          5857:                                        &fld_len, &num_idx, 0, &pos)) != HASH_KEY_NON_EXISTANT) {
        !          5858:                if (key_type == HASH_KEY_IS_LONG) {
        !          5859:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects associative array for values to be inserted");
        !          5860:                        goto cleanup;
        !          5861:                }
        !          5862:                smart_str_appendl(&querystr, fld, fld_len - 1);
        !          5863:                smart_str_appendc(&querystr, ',');
        !          5864:                zend_hash_move_forward_ex(Z_ARRVAL_P(var_array), &pos);
        !          5865:        }
        !          5866:        querystr.len--;
        !          5867:        smart_str_appends(&querystr, ") VALUES (");
        !          5868:        
        !          5869:        /* make values string */
        !          5870:        for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(var_array), &pos);
        !          5871:                 zend_hash_get_current_data_ex(Z_ARRVAL_P(var_array), (void **)&val, &pos) == SUCCESS;
        !          5872:                 zend_hash_move_forward_ex(Z_ARRVAL_P(var_array), &pos)) {
        !          5873:                
        !          5874:                /* we can avoid the key_type check here, because we tested it in the other loop */
        !          5875:                switch(Z_TYPE_PP(val)) {
        !          5876:                        case IS_STRING:
        !          5877:                                smart_str_appendl(&querystr, Z_STRVAL_PP(val), Z_STRLEN_PP(val));
        !          5878:                                break;
        !          5879:                        case IS_LONG:
        !          5880:                                smart_str_append_long(&querystr, Z_LVAL_PP(val));
        !          5881:                                break;
        !          5882:                        case IS_DOUBLE:
        !          5883:                                smart_str_appendl(&querystr, buf, snprintf(buf, sizeof(buf), "%F", Z_DVAL_PP(val)));
        !          5884:                                break;
        !          5885:                        default:
        !          5886:                                /* should not happen */
        !          5887:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Report this error to php-dev@lists.php.net, type = %d", Z_TYPE_PP(val));
        !          5888:                                goto cleanup;
        !          5889:                                break;
        !          5890:                }
        !          5891:                smart_str_appendc(&querystr, ',');
        !          5892:        }
        !          5893:        /* Remove the trailing "," */
        !          5894:        querystr.len--;
        !          5895:        smart_str_appends(&querystr, ");");
        !          5896: 
        !          5897: no_values:
        !          5898: 
        !          5899:        smart_str_0(&querystr);
        !          5900: 
        !          5901:        if ((opt & (PGSQL_DML_EXEC|PGSQL_DML_ASYNC)) &&
        !          5902:                do_exec(&querystr, PGRES_COMMAND_OK, pg_link, (opt & PGSQL_CONV_OPTS) TSRMLS_CC) == 0) {
        !          5903:                ret = SUCCESS;
        !          5904:        }
        !          5905:        else if (opt & PGSQL_DML_STRING) {
        !          5906:                ret = SUCCESS;
        !          5907:        }
        !          5908:        
        !          5909: cleanup:
        !          5910:        if (!(opt & PGSQL_DML_NO_CONV) && converted) {
        !          5911:                zval_dtor(converted);                   
        !          5912:                FREE_ZVAL(converted);
        !          5913:        }
        !          5914:        if (ret == SUCCESS && (opt & PGSQL_DML_STRING)) {
        !          5915:                *sql = querystr.c;
        !          5916:        }
        !          5917:        else {
        !          5918:                smart_str_free(&querystr);
        !          5919:        }
        !          5920:        return ret;
        !          5921: }
        !          5922: /* }}} */
        !          5923: 
        !          5924: /* {{{ proto mixed pg_insert(resource db, string table, array values[, int options])
        !          5925:    Insert values (filed=>value) to table */
        !          5926: PHP_FUNCTION(pg_insert)
        !          5927: {
        !          5928:        zval *pgsql_link, *values;
        !          5929:        char *table, *sql = NULL;
        !          5930:        int table_len;
        !          5931:        ulong option = PGSQL_DML_EXEC;
        !          5932:        PGconn *pg_link;
        !          5933:        int id = -1, argc = ZEND_NUM_ARGS();
        !          5934: 
        !          5935:        if (zend_parse_parameters(argc TSRMLS_CC, "rsa|l",
        !          5936:                                                          &pgsql_link, &table, &table_len, &values, &option) == FAILURE) {
        !          5937:                return;
        !          5938:        }
        !          5939:        if (option & ~(PGSQL_CONV_OPTS|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_ASYNC|PGSQL_DML_STRING)) {
        !          5940:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is specified");
        !          5941:                RETURN_FALSE;
        !          5942:        }
        !          5943:        
        !          5944:        ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          5945: 
        !          5946:        if (php_pgsql_flush_query(pg_link TSRMLS_CC)) {
        !          5947:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected unhandled result(s) in connection");
        !          5948:        }
        !          5949:        if (php_pgsql_insert(pg_link, table, values, option, &sql TSRMLS_CC) == FAILURE) {
        !          5950:                RETURN_FALSE;
        !          5951:        }
        !          5952:        if (option & PGSQL_DML_STRING) {
        !          5953:                RETURN_STRING(sql, 0);
        !          5954:        }
        !          5955:        RETURN_TRUE;
        !          5956: }
        !          5957: /* }}} */
        !          5958: 
        !          5959: static inline int build_assignment_string(smart_str *querystr, HashTable *ht, int where_cond, const char *pad, int pad_len TSRMLS_DC)
        !          5960: {
        !          5961:        HashPosition pos;
        !          5962:        uint fld_len;
        !          5963:        int key_type;
        !          5964:        ulong num_idx;
        !          5965:        char *fld;
        !          5966:        char buf[256];
        !          5967:        zval **val;
        !          5968: 
        !          5969:        for (zend_hash_internal_pointer_reset_ex(ht, &pos);
        !          5970:                 zend_hash_get_current_data_ex(ht, (void **)&val, &pos) == SUCCESS;
        !          5971:                 zend_hash_move_forward_ex(ht, &pos)) {
        !          5972:                 key_type = zend_hash_get_current_key_ex(ht, &fld, &fld_len, &num_idx, 0, &pos);                
        !          5973:                if (key_type == HASH_KEY_IS_LONG) {
        !          5974:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects associative array for values to be inserted");
        !          5975:                        return -1;
        !          5976:                }
        !          5977:                smart_str_appendl(querystr, fld, fld_len - 1);
        !          5978:                if (where_cond && Z_TYPE_PP(val) == IS_STRING && !strcmp(Z_STRVAL_PP(val), "NULL")) {
        !          5979:                        smart_str_appends(querystr, " IS ");
        !          5980:                } else {
        !          5981:                        smart_str_appendc(querystr, '=');
        !          5982:                }
        !          5983:                
        !          5984:                switch(Z_TYPE_PP(val)) {
        !          5985:                        case IS_STRING:
        !          5986:                                smart_str_appendl(querystr, Z_STRVAL_PP(val), Z_STRLEN_PP(val));
        !          5987:                                break;
        !          5988:                        case IS_LONG:
        !          5989:                                smart_str_append_long(querystr, Z_LVAL_PP(val));
        !          5990:                                break;
        !          5991:                        case IS_DOUBLE:
        !          5992:                                smart_str_appendl(querystr, buf, MIN(snprintf(buf, sizeof(buf), "%F", Z_DVAL_PP(val)), sizeof(buf)-1));
        !          5993:                                break;
        !          5994:                        default:
        !          5995:                                /* should not happen */
        !          5996:                                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects scaler values other than NULL. Need to convert?");
        !          5997:                                return -1;
        !          5998:                }
        !          5999:                smart_str_appendl(querystr, pad, pad_len);
        !          6000:        }
        !          6001:        querystr->len -= pad_len;
        !          6002: 
        !          6003:        return 0;
        !          6004: }
        !          6005: 
        !          6006: /* {{{ php_pgsql_update
        !          6007:  */
        !          6008: PHP_PGSQL_API int php_pgsql_update(PGconn *pg_link, const char *table, zval *var_array, zval *ids_array, ulong opt, char **sql TSRMLS_DC) 
        !          6009: {
        !          6010:        zval *var_converted = NULL, *ids_converted = NULL;
        !          6011:        smart_str querystr = {0};
        !          6012:        int ret = FAILURE;
        !          6013: 
        !          6014:        assert(pg_link != NULL);
        !          6015:        assert(table != NULL);
        !          6016:        assert(Z_TYPE_P(var_array) == IS_ARRAY);
        !          6017:        assert(Z_TYPE_P(ids_array) == IS_ARRAY);
        !          6018:        assert(!(opt & ~(PGSQL_CONV_OPTS|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_STRING)));
        !          6019: 
        !          6020:        if (zend_hash_num_elements(Z_ARRVAL_P(var_array)) == 0
        !          6021:                        || zend_hash_num_elements(Z_ARRVAL_P(ids_array)) == 0) {
        !          6022:                return FAILURE;
        !          6023:        }
        !          6024: 
        !          6025:        if (!(opt & PGSQL_DML_NO_CONV)) {
        !          6026:                MAKE_STD_ZVAL(var_converted);
        !          6027:                array_init(var_converted);
        !          6028:                if (php_pgsql_convert(pg_link, table, var_array, var_converted, (opt & PGSQL_CONV_OPTS) TSRMLS_CC) == FAILURE) {
        !          6029:                        goto cleanup;
        !          6030:                }
        !          6031:                var_array = var_converted;
        !          6032:                MAKE_STD_ZVAL(ids_converted);
        !          6033:                array_init(ids_converted);
        !          6034:                if (php_pgsql_convert(pg_link, table, ids_array, ids_converted, (opt & PGSQL_CONV_OPTS) TSRMLS_CC) == FAILURE) {
        !          6035:                        goto cleanup;
        !          6036:                }
        !          6037:                ids_array = ids_converted;
        !          6038:        }
        !          6039: 
        !          6040:        smart_str_appends(&querystr, "UPDATE ");
        !          6041:        smart_str_appends(&querystr, table);
        !          6042:        smart_str_appends(&querystr, " SET ");
        !          6043: 
        !          6044:        if (build_assignment_string(&querystr, Z_ARRVAL_P(var_array), 0, ",", 1 TSRMLS_CC))
        !          6045:                goto cleanup;
        !          6046:        
        !          6047:        smart_str_appends(&querystr, " WHERE ");
        !          6048:        
        !          6049:        if (build_assignment_string(&querystr, Z_ARRVAL_P(ids_array), 1, " AND ", sizeof(" AND ")-1 TSRMLS_CC))
        !          6050:                goto cleanup;
        !          6051: 
        !          6052:        smart_str_appendc(&querystr, ';');      
        !          6053:        smart_str_0(&querystr);
        !          6054: 
        !          6055:        if ((opt & PGSQL_DML_EXEC) && do_exec(&querystr, PGRES_COMMAND_OK, pg_link, opt TSRMLS_CC) == 0) {
        !          6056:                ret = SUCCESS;
        !          6057:        } else if (opt & PGSQL_DML_STRING) {
        !          6058:                ret = SUCCESS;
        !          6059:        }
        !          6060: 
        !          6061: cleanup:
        !          6062:        if (var_converted) {
        !          6063:                zval_dtor(var_converted);
        !          6064:                FREE_ZVAL(var_converted);
        !          6065:        }
        !          6066:        if (ids_converted) {
        !          6067:                zval_dtor(ids_converted);
        !          6068:                FREE_ZVAL(ids_converted);
        !          6069:        }
        !          6070:        if (ret == SUCCESS && (opt & PGSQL_DML_STRING)) {
        !          6071:                *sql = querystr.c;
        !          6072:        }
        !          6073:        else {
        !          6074:                smart_str_free(&querystr);
        !          6075:        }
        !          6076:        return ret;
        !          6077: }
        !          6078: /* }}} */
        !          6079: 
        !          6080: /* {{{ proto mixed pg_update(resource db, string table, array fields, array ids[, int options])
        !          6081:    Update table using values (field=>value) and ids (id=>value) */
        !          6082: PHP_FUNCTION(pg_update)
        !          6083: {
        !          6084:        zval *pgsql_link, *values, *ids;
        !          6085:        char *table, *sql = NULL;
        !          6086:        int table_len;
        !          6087:        ulong option =  PGSQL_DML_EXEC;
        !          6088:        PGconn *pg_link;
        !          6089:        int id = -1, argc = ZEND_NUM_ARGS();
        !          6090: 
        !          6091:        if (zend_parse_parameters(argc TSRMLS_CC, "rsaa|l",
        !          6092:                                                          &pgsql_link, &table, &table_len, &values, &ids, &option) == FAILURE) {
        !          6093:                return;
        !          6094:        }
        !          6095:        if (option & ~(PGSQL_CONV_OPTS|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_STRING)) {
        !          6096:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is specified");
        !          6097:                RETURN_FALSE;
        !          6098:        }
        !          6099:        
        !          6100:        ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          6101: 
        !          6102:        if (php_pgsql_flush_query(pg_link TSRMLS_CC)) {
        !          6103:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected unhandled result(s) in connection");
        !          6104:        }
        !          6105:        if (php_pgsql_update(pg_link, table, values, ids, option, &sql TSRMLS_CC) == FAILURE) {
        !          6106:                RETURN_FALSE;
        !          6107:        }
        !          6108:        if (option & PGSQL_DML_STRING) {
        !          6109:                RETURN_STRING(sql, 0);
        !          6110:        }
        !          6111:        RETURN_TRUE;
        !          6112: } 
        !          6113: /* }}} */
        !          6114: 
        !          6115: /* {{{ php_pgsql_delete
        !          6116:  */
        !          6117: PHP_PGSQL_API int php_pgsql_delete(PGconn *pg_link, const char *table, zval *ids_array, ulong opt, char **sql TSRMLS_DC) 
        !          6118: {
        !          6119:        zval *ids_converted = NULL;
        !          6120:        smart_str querystr = {0};
        !          6121:        int ret = FAILURE;
        !          6122: 
        !          6123:        assert(pg_link != NULL);
        !          6124:        assert(table != NULL);
        !          6125:        assert(Z_TYPE_P(ids_array) == IS_ARRAY);
        !          6126:        assert(!(opt & ~(PGSQL_CONV_FORCE_NULL|PGSQL_DML_EXEC|PGSQL_DML_STRING)));
        !          6127:        
        !          6128:        if (zend_hash_num_elements(Z_ARRVAL_P(ids_array)) == 0) {
        !          6129:                return FAILURE;
        !          6130:        }
        !          6131: 
        !          6132:        if (!(opt & PGSQL_DML_NO_CONV)) {
        !          6133:                MAKE_STD_ZVAL(ids_converted);
        !          6134:                array_init(ids_converted);
        !          6135:                if (php_pgsql_convert(pg_link, table, ids_array, ids_converted, (opt & PGSQL_CONV_OPTS) TSRMLS_CC) == FAILURE) {
        !          6136:                        goto cleanup;
        !          6137:                }
        !          6138:                ids_array = ids_converted;
        !          6139:        }
        !          6140: 
        !          6141:        smart_str_appends(&querystr, "DELETE FROM ");
        !          6142:        smart_str_appends(&querystr, table);
        !          6143:        smart_str_appends(&querystr, " WHERE ");
        !          6144: 
        !          6145:        if (build_assignment_string(&querystr, Z_ARRVAL_P(ids_array), 1, " AND ", sizeof(" AND ")-1 TSRMLS_CC))
        !          6146:                goto cleanup;
        !          6147: 
        !          6148:        smart_str_appendc(&querystr, ';');
        !          6149:        smart_str_0(&querystr);
        !          6150: 
        !          6151:        if ((opt & PGSQL_DML_EXEC) && do_exec(&querystr, PGRES_COMMAND_OK, pg_link, opt TSRMLS_CC) == 0) {
        !          6152:                ret = SUCCESS;
        !          6153:        } else if (opt & PGSQL_DML_STRING) {
        !          6154:                ret = SUCCESS;
        !          6155:        }
        !          6156: 
        !          6157: cleanup:
        !          6158:        if (!(opt & PGSQL_DML_NO_CONV)) {
        !          6159:                zval_dtor(ids_converted);                       
        !          6160:                FREE_ZVAL(ids_converted);
        !          6161:        }
        !          6162:        if (ret == SUCCESS && (opt & PGSQL_DML_STRING)) {
        !          6163:                *sql = querystr.c;
        !          6164:        }
        !          6165:        else {
        !          6166:                smart_str_free(&querystr);
        !          6167:        }
        !          6168:        return ret;
        !          6169: }
        !          6170: /* }}} */
        !          6171: 
        !          6172: /* {{{ proto mixed pg_delete(resource db, string table, array ids[, int options])
        !          6173:    Delete records has ids (id=>value) */
        !          6174: PHP_FUNCTION(pg_delete)
        !          6175: {
        !          6176:        zval *pgsql_link, *ids;
        !          6177:        char *table, *sql = NULL;
        !          6178:        int table_len;
        !          6179:        ulong option = PGSQL_DML_EXEC;
        !          6180:        PGconn *pg_link;
        !          6181:        int id = -1, argc = ZEND_NUM_ARGS();
        !          6182: 
        !          6183:        if (zend_parse_parameters(argc TSRMLS_CC, "rsa|l",
        !          6184:                                                          &pgsql_link, &table, &table_len, &ids, &option) == FAILURE) {
        !          6185:                return;
        !          6186:        }
        !          6187:        if (option & ~(PGSQL_CONV_FORCE_NULL|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_STRING)) {
        !          6188:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is specified");
        !          6189:                RETURN_FALSE;
        !          6190:        }
        !          6191:        
        !          6192:        ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          6193: 
        !          6194:        if (php_pgsql_flush_query(pg_link TSRMLS_CC)) {
        !          6195:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected unhandled result(s) in connection");
        !          6196:        }
        !          6197:        if (php_pgsql_delete(pg_link, table, ids, option, &sql TSRMLS_CC) == FAILURE) {
        !          6198:                RETURN_FALSE;
        !          6199:        }
        !          6200:        if (option & PGSQL_DML_STRING) {
        !          6201:                RETURN_STRING(sql, 0);
        !          6202:        }
        !          6203:        RETURN_TRUE;
        !          6204: } 
        !          6205: /* }}} */
        !          6206: 
        !          6207: /* {{{ php_pgsql_result2array
        !          6208:  */
        !          6209: PHP_PGSQL_API int php_pgsql_result2array(PGresult *pg_result, zval *ret_array TSRMLS_DC) 
        !          6210: {
        !          6211:        zval *row;
        !          6212:        char *field_name;
        !          6213:        size_t num_fields;
        !          6214:        int pg_numrows, pg_row;
        !          6215:        uint i;
        !          6216:        assert(Z_TYPE_P(ret_array) == IS_ARRAY);
        !          6217: 
        !          6218:        if ((pg_numrows = PQntuples(pg_result)) <= 0) {
        !          6219:                return FAILURE;
        !          6220:        }
        !          6221:        for (pg_row = 0; pg_row < pg_numrows; pg_row++) {
        !          6222:                MAKE_STD_ZVAL(row);
        !          6223:                array_init(row);
        !          6224:                add_index_zval(ret_array, pg_row, row);
        !          6225:                for (i = 0, num_fields = PQnfields(pg_result); i < num_fields; i++) {
        !          6226:                        if (PQgetisnull(pg_result, pg_row, i)) {
        !          6227:                                field_name = PQfname(pg_result, i);
        !          6228:                                add_assoc_null(row, field_name);
        !          6229:                        } else {
        !          6230:                                char *element = PQgetvalue(pg_result, pg_row, i);
        !          6231:                                if (element) {
        !          6232:                                        char *data;
        !          6233:                                        size_t data_len;
        !          6234:                                        const size_t element_len = strlen(element);
        !          6235: 
        !          6236:                                        if (PG(magic_quotes_runtime)) {
        !          6237:                                                data = php_addslashes(element, element_len, &data_len, 0 TSRMLS_CC);
        !          6238:                                        } else {
        !          6239:                                                data = safe_estrndup(element, element_len);
        !          6240:                                                data_len = element_len;
        !          6241:                                        }
        !          6242:                                        field_name = PQfname(pg_result, i);
        !          6243:                                        add_assoc_stringl(row, field_name, data, data_len, 0);
        !          6244:                                }
        !          6245:                        }
        !          6246:                }
        !          6247:        }
        !          6248:        return SUCCESS;
        !          6249: }
        !          6250: /* }}} */
        !          6251: 
        !          6252: /* {{{ php_pgsql_select
        !          6253:  */
        !          6254: PHP_PGSQL_API int php_pgsql_select(PGconn *pg_link, const char *table, zval *ids_array, zval *ret_array, ulong opt, char **sql TSRMLS_DC) 
        !          6255: {
        !          6256:        zval *ids_converted = NULL;
        !          6257:        smart_str querystr = {0};
        !          6258:        int ret = FAILURE;
        !          6259:        PGresult *pg_result;
        !          6260: 
        !          6261:        assert(pg_link != NULL);
        !          6262:        assert(table != NULL);
        !          6263:        assert(Z_TYPE_P(ids_array) == IS_ARRAY);
        !          6264:        assert(Z_TYPE_P(ret_array) == IS_ARRAY);
        !          6265:        assert(!(opt & ~(PGSQL_CONV_OPTS|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_ASYNC|PGSQL_DML_STRING)));
        !          6266:        
        !          6267:        if (zend_hash_num_elements(Z_ARRVAL_P(ids_array)) == 0) {
        !          6268:                return FAILURE;
        !          6269:        }
        !          6270: 
        !          6271:        if (!(opt & PGSQL_DML_NO_CONV)) {
        !          6272:                MAKE_STD_ZVAL(ids_converted);
        !          6273:                array_init(ids_converted);
        !          6274:                if (php_pgsql_convert(pg_link, table, ids_array, ids_converted, (opt & PGSQL_CONV_OPTS) TSRMLS_CC) == FAILURE) {
        !          6275:                        goto cleanup;
        !          6276:                }
        !          6277:                ids_array = ids_converted;
        !          6278:        }
        !          6279: 
        !          6280:        smart_str_appends(&querystr, "SELECT * FROM ");
        !          6281:        smart_str_appends(&querystr, table);
        !          6282:        smart_str_appends(&querystr, " WHERE ");
        !          6283: 
        !          6284:        if (build_assignment_string(&querystr, Z_ARRVAL_P(ids_array), 1, " AND ", sizeof(" AND ")-1 TSRMLS_CC))
        !          6285:                goto cleanup;
        !          6286: 
        !          6287:        smart_str_appendc(&querystr, ';');
        !          6288:        smart_str_0(&querystr);
        !          6289: 
        !          6290:        pg_result = PQexec(pg_link, querystr.c);
        !          6291:        if (PQresultStatus(pg_result) == PGRES_TUPLES_OK) {
        !          6292:                ret = php_pgsql_result2array(pg_result, ret_array TSRMLS_CC);
        !          6293:        } else {
        !          6294:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Failed to execute '%s'", querystr.c);
        !          6295:        }
        !          6296:        PQclear(pg_result);
        !          6297: 
        !          6298: cleanup:
        !          6299:        if (!(opt & PGSQL_DML_NO_CONV)) {
        !          6300:                zval_dtor(ids_converted);                       
        !          6301:                FREE_ZVAL(ids_converted);
        !          6302:        }
        !          6303:        if (ret == SUCCESS && (opt & PGSQL_DML_STRING)) {
        !          6304:                *sql = querystr.c;
        !          6305:        }
        !          6306:        else {
        !          6307:                smart_str_free(&querystr);
        !          6308:        }
        !          6309:        return ret;
        !          6310: }
        !          6311: /* }}} */
        !          6312: 
        !          6313: /* {{{ proto mixed pg_select(resource db, string table, array ids[, int options])
        !          6314:    Select records that has ids (id=>value) */
        !          6315: PHP_FUNCTION(pg_select)
        !          6316: {
        !          6317:        zval *pgsql_link, *ids;
        !          6318:        char *table, *sql = NULL;
        !          6319:        int table_len;
        !          6320:        ulong option = PGSQL_DML_EXEC;
        !          6321:        PGconn *pg_link;
        !          6322:        int id = -1, argc = ZEND_NUM_ARGS();
        !          6323: 
        !          6324:        if (zend_parse_parameters(argc TSRMLS_CC, "rsa|l",
        !          6325:                                                          &pgsql_link, &table, &table_len, &ids, &option) == FAILURE) {
        !          6326:                return;
        !          6327:        }
        !          6328:        if (option & ~(PGSQL_CONV_FORCE_NULL|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_ASYNC|PGSQL_DML_STRING)) {
        !          6329:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is specified");
        !          6330:                RETURN_FALSE;
        !          6331:        }
        !          6332:        
        !          6333:        ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
        !          6334: 
        !          6335:        if (php_pgsql_flush_query(pg_link TSRMLS_CC)) {
        !          6336:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected unhandled result(s) in connection");
        !          6337:        }
        !          6338:        array_init(return_value);
        !          6339:        if (php_pgsql_select(pg_link, table, ids, return_value, option, &sql TSRMLS_CC) == FAILURE) {
        !          6340:                zval_dtor(return_value);
        !          6341:                RETURN_FALSE;
        !          6342:        }
        !          6343:        if (option & PGSQL_DML_STRING) {
        !          6344:                zval_dtor(return_value);
        !          6345:                RETURN_STRING(sql, 0);
        !          6346:        }
        !          6347:        return;
        !          6348: } 
        !          6349: /* }}} */
        !          6350: 
        !          6351: #endif
        !          6352: 
        !          6353: /*
        !          6354:  * Local variables:
        !          6355:  * tab-width: 4
        !          6356:  * c-basic-offset: 4
        !          6357:  * End:
        !          6358:  * vim600: sw=4 ts=4 fdm=marker
        !          6359:  * vim<600: sw=4 ts=4
        !          6360:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>