Return to pgsql.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / pgsql |
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: */