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, ¬ice->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 **)¬ice, 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, ¶m, &len) == SUCCESS) {
! 1496: id = -1;
! 1497: } else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", ¶m, &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 **)¬ice) == 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 **)¬_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>