1999-04-22 10:48:28 +08:00
|
|
|
/*
|
|
|
|
+----------------------------------------------------------------------+
|
2001-12-11 23:32:16 +08:00
|
|
|
| PHP Version 4 |
|
1999-04-22 10:48:28 +08:00
|
|
|
+----------------------------------------------------------------------+
|
2001-12-11 23:32:16 +08:00
|
|
|
| Copyright (c) 1997-2002 The PHP Group |
|
1999-04-22 10:48:28 +08:00
|
|
|
+----------------------------------------------------------------------+
|
2000-05-18 23:34:45 +08:00
|
|
|
| This source file is subject to version 2.02 of the PHP license, |
|
1999-07-16 21:13:16 +08:00
|
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
|
|
| available at through the world-wide-web at |
|
2000-05-18 23:34:45 +08:00
|
|
|
| http://www.php.net/license/2_02.txt. |
|
1999-07-16 21:13:16 +08:00
|
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
|
|
| license@php.net so we can mail you a copy immediately. |
|
1999-04-22 10:48:28 +08:00
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| Authors: Zeev Suraski <zeev@zend.com> |
|
2001-12-17 08:24:59 +08:00
|
|
|
| Jouni Ahto <jouni.ahto@exdec.fi> |
|
|
|
|
| Yasuo Ohgaki <yohgaki@php.net> |
|
|
|
|
| Youichi Iwakiri <yiwakiri@st.rim.or.jp> (pg_copy_*) |
|
1999-04-22 10:48:28 +08:00
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* $Id$ */
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2000-05-02 13:27:35 +08:00
|
|
|
#define PHP_PGSQL_PRIVATE 1
|
|
|
|
|
2001-05-24 18:07:29 +08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2002-05-11 11:01:08 +08:00
|
|
|
#define SMART_STR_PREALLOC 512
|
|
|
|
|
1999-04-22 10:48:28 +08:00
|
|
|
#include "php.h"
|
2000-02-06 01:26:35 +08:00
|
|
|
#include "php_ini.h"
|
1999-12-05 03:19:57 +08:00
|
|
|
#include "ext/standard/php_standard.h"
|
2002-04-21 17:46:29 +08:00
|
|
|
#include "ext/standard/php_smart_str.h"
|
2000-02-06 00:12:23 +08:00
|
|
|
#include "php_pgsql.h"
|
1999-04-22 10:48:28 +08:00
|
|
|
#include "php_globals.h"
|
|
|
|
|
|
|
|
#if HAVE_PGSQL
|
|
|
|
|
2001-02-20 00:31:17 +08:00
|
|
|
#ifndef InvalidOid
|
|
|
|
#define InvalidOid ((Oid) 0)
|
|
|
|
#endif
|
1999-04-22 10:48:28 +08:00
|
|
|
|
1999-07-17 01:19:11 +08:00
|
|
|
#define PGSQL_ASSOC 1<<0
|
|
|
|
#define PGSQL_NUM 1<<1
|
|
|
|
#define PGSQL_BOTH (PGSQL_ASSOC|PGSQL_NUM)
|
|
|
|
|
2002-04-08 08:43:58 +08:00
|
|
|
#define PGSQL_STATUS_LONG 1
|
|
|
|
#define PGSQL_STATUS_STRING 2
|
2001-12-17 08:24:59 +08:00
|
|
|
|
2002-04-20 11:03:42 +08:00
|
|
|
#define PGSQL_MAX_LENGTH_OF_LONG 30
|
|
|
|
#define PGSQL_MAX_LENGTH_OF_DOUBLE 60
|
|
|
|
|
2002-04-21 18:22:31 +08:00
|
|
|
#define PGSQL_RETURN_OID(oid) do { \
|
|
|
|
if (oid > LONG_MAX) { \
|
|
|
|
smart_str s = {0}; \
|
|
|
|
smart_str_append_unsigned(&s, oid); \
|
|
|
|
smart_str_0(&s); \
|
|
|
|
RETURN_STRINGL(s.c, s.len, 0); \
|
|
|
|
} \
|
|
|
|
RETURN_LONG((long)oid); \
|
|
|
|
} while(0)
|
|
|
|
|
2002-04-20 11:03:42 +08:00
|
|
|
|
2002-03-29 19:24:54 +08:00
|
|
|
#if HAVE_PQSETNONBLOCKING
|
|
|
|
#define PQ_SETNONBLOCKING(pg_link, flag) PQsetnonblocking(pg_link, flag)
|
|
|
|
#else
|
|
|
|
#define PQ_SETNONBLOCKING(pg_link, flag) 0
|
|
|
|
#endif
|
|
|
|
|
2002-09-05 06:25:13 +08:00
|
|
|
#define CHECK_DEFAULT_LINK(x) if ((x) == -1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "No PostgreSQL link opened yet"); }
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ pgsql_functions[]
|
|
|
|
*/
|
1999-04-22 10:48:28 +08:00
|
|
|
function_entry pgsql_functions[] = {
|
2001-12-17 08:24:59 +08:00
|
|
|
/* connection functions */
|
1999-12-18 19:38:04 +08:00
|
|
|
PHP_FE(pg_connect, NULL)
|
|
|
|
PHP_FE(pg_pconnect, NULL)
|
|
|
|
PHP_FE(pg_close, NULL)
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FE(pg_connection_status, NULL)
|
|
|
|
PHP_FE(pg_connection_busy, NULL)
|
|
|
|
PHP_FE(pg_connection_reset, NULL)
|
|
|
|
PHP_FE(pg_host, NULL)
|
1999-12-18 19:38:04 +08:00
|
|
|
PHP_FE(pg_dbname, NULL)
|
|
|
|
PHP_FE(pg_port, NULL)
|
|
|
|
PHP_FE(pg_tty, NULL)
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FE(pg_options, NULL)
|
|
|
|
/* query functions */
|
|
|
|
PHP_FE(pg_query, NULL)
|
|
|
|
PHP_FE(pg_send_query, NULL)
|
|
|
|
PHP_FE(pg_cancel_query, NULL)
|
|
|
|
/* result functions */
|
|
|
|
PHP_FE(pg_fetch_result, NULL)
|
1999-12-18 19:38:04 +08:00
|
|
|
PHP_FE(pg_fetch_row, NULL)
|
|
|
|
PHP_FE(pg_fetch_array, NULL)
|
|
|
|
PHP_FE(pg_fetch_object, NULL)
|
2002-07-21 15:25:10 +08:00
|
|
|
PHP_FE(pg_fetch_all, NULL)
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FE(pg_affected_rows,NULL)
|
|
|
|
PHP_FE(pg_get_result, NULL)
|
|
|
|
PHP_FE(pg_result_status,NULL)
|
|
|
|
PHP_FE(pg_free_result, NULL)
|
|
|
|
PHP_FE(pg_last_oid, NULL)
|
|
|
|
PHP_FE(pg_num_rows, NULL)
|
|
|
|
PHP_FE(pg_num_fields, NULL)
|
|
|
|
PHP_FE(pg_field_name, NULL)
|
|
|
|
PHP_FE(pg_field_num, NULL)
|
|
|
|
PHP_FE(pg_field_size, NULL)
|
|
|
|
PHP_FE(pg_field_type, NULL)
|
|
|
|
PHP_FE(pg_field_prtlen, NULL)
|
|
|
|
PHP_FE(pg_field_is_null,NULL)
|
|
|
|
/* error message functions */
|
|
|
|
PHP_FE(pg_result_error, NULL)
|
|
|
|
PHP_FE(pg_last_error, NULL)
|
|
|
|
PHP_FE(pg_last_notice, NULL)
|
|
|
|
/* copy functions */
|
2000-09-12 05:28:47 +08:00
|
|
|
PHP_FE(pg_put_line, NULL)
|
|
|
|
PHP_FE(pg_end_copy, NULL)
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FE(pg_copy_to, NULL)
|
|
|
|
PHP_FE(pg_copy_from, NULL)
|
|
|
|
/* debug functions */
|
|
|
|
PHP_FE(pg_trace, NULL)
|
|
|
|
PHP_FE(pg_untrace, NULL)
|
|
|
|
/* large object functions */
|
|
|
|
PHP_FE(pg_lo_create, NULL)
|
|
|
|
PHP_FE(pg_lo_unlink, NULL)
|
|
|
|
PHP_FE(pg_lo_open, NULL)
|
|
|
|
PHP_FE(pg_lo_close, NULL)
|
|
|
|
PHP_FE(pg_lo_read, NULL)
|
|
|
|
PHP_FE(pg_lo_write, NULL)
|
|
|
|
PHP_FE(pg_lo_read_all, NULL)
|
|
|
|
PHP_FE(pg_lo_import, NULL)
|
|
|
|
PHP_FE(pg_lo_export, NULL)
|
|
|
|
PHP_FE(pg_lo_seek, NULL)
|
|
|
|
PHP_FE(pg_lo_tell, NULL)
|
|
|
|
/* utility functions */
|
|
|
|
#if HAVE_PQESCAPE
|
|
|
|
PHP_FE(pg_escape_string,NULL)
|
|
|
|
PHP_FE(pg_escape_bytea, NULL)
|
|
|
|
#endif
|
2002-04-25 15:09:45 +08:00
|
|
|
#if HAVE_PQCLIENTENCODING
|
2000-09-13 12:13:36 +08:00
|
|
|
PHP_FE(pg_client_encoding, NULL)
|
|
|
|
PHP_FE(pg_set_client_encoding, NULL)
|
2002-04-25 15:09:45 +08:00
|
|
|
#endif
|
2002-04-08 09:37:38 +08:00
|
|
|
/* misc function */
|
|
|
|
PHP_FE(pg_metadata, NULL)
|
|
|
|
PHP_FE(pg_convert, NULL)
|
|
|
|
PHP_FE(pg_insert, NULL)
|
|
|
|
PHP_FE(pg_update, NULL)
|
|
|
|
PHP_FE(pg_delete, NULL)
|
|
|
|
PHP_FE(pg_select, NULL)
|
2001-12-17 08:24:59 +08:00
|
|
|
/* aliases for downwards compatibility */
|
|
|
|
PHP_FALIAS(pg_exec, pg_query, NULL)
|
|
|
|
PHP_FALIAS(pg_getlastoid, pg_last_oid, NULL)
|
|
|
|
PHP_FALIAS(pg_cmdtuples, pg_affected_rows, NULL)
|
|
|
|
PHP_FALIAS(pg_errormessage, pg_last_error, NULL)
|
|
|
|
PHP_FALIAS(pg_numrows, pg_num_rows, NULL)
|
|
|
|
PHP_FALIAS(pg_numfields, pg_num_fields, NULL)
|
|
|
|
PHP_FALIAS(pg_fieldname, pg_field_name, NULL)
|
|
|
|
PHP_FALIAS(pg_fieldsize, pg_field_size, NULL)
|
|
|
|
PHP_FALIAS(pg_fieldtype, pg_field_type, NULL)
|
|
|
|
PHP_FALIAS(pg_fieldnum, pg_field_num, NULL)
|
|
|
|
PHP_FALIAS(pg_fieldprtlen, pg_field_prtlen, NULL)
|
|
|
|
PHP_FALIAS(pg_fieldisnull, pg_field_is_null, NULL)
|
|
|
|
PHP_FALIAS(pg_freeresult, pg_free_result, NULL)
|
|
|
|
PHP_FALIAS(pg_result, pg_fetch_result, NULL)
|
|
|
|
PHP_FALIAS(pg_loreadall, pg_lo_read_all, NULL)
|
|
|
|
PHP_FALIAS(pg_locreate, pg_lo_create, NULL)
|
|
|
|
PHP_FALIAS(pg_lounlink, pg_lo_unlink, NULL)
|
|
|
|
PHP_FALIAS(pg_loopen, pg_lo_open, NULL)
|
2002-02-06 15:25:51 +08:00
|
|
|
PHP_FALIAS(pg_loclose, pg_lo_close, NULL)
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FALIAS(pg_loread, pg_lo_read, NULL)
|
|
|
|
PHP_FALIAS(pg_lowrite, pg_lo_write, NULL)
|
|
|
|
PHP_FALIAS(pg_loimport, pg_lo_import, NULL)
|
|
|
|
PHP_FALIAS(pg_loexport, pg_lo_export, NULL)
|
2002-04-25 15:09:45 +08:00
|
|
|
#if HAVE_PQCLIENTENCODING
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FALIAS(pg_clientencoding, pg_client_encoding, NULL)
|
2000-09-13 12:13:36 +08:00
|
|
|
PHP_FALIAS(pg_setclientencoding, pg_set_client_encoding, NULL)
|
2002-04-25 15:09:45 +08:00
|
|
|
#endif
|
2002-02-06 15:25:51 +08:00
|
|
|
{NULL, NULL, NULL}
|
1999-04-22 10:48:28 +08:00
|
|
|
};
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ pgsql_module_entry
|
|
|
|
*/
|
1999-12-18 04:55:31 +08:00
|
|
|
zend_module_entry pgsql_module_entry = {
|
2001-10-12 07:33:59 +08:00
|
|
|
STANDARD_MODULE_HEADER,
|
2000-05-24 14:48:04 +08:00
|
|
|
"pgsql",
|
|
|
|
pgsql_functions,
|
|
|
|
PHP_MINIT(pgsql),
|
|
|
|
PHP_MSHUTDOWN(pgsql),
|
|
|
|
PHP_RINIT(pgsql),
|
2001-02-14 02:28:24 +08:00
|
|
|
PHP_RSHUTDOWN(pgsql),
|
2000-05-24 14:48:04 +08:00
|
|
|
PHP_MINFO(pgsql),
|
2002-08-24 04:57:30 +08:00
|
|
|
NO_VERSION_YET,
|
2000-05-24 14:48:04 +08:00
|
|
|
STANDARD_MODULE_PROPERTIES
|
1999-04-22 10:48:28 +08:00
|
|
|
};
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2000-05-23 17:33:51 +08:00
|
|
|
#ifdef COMPILE_DL_PGSQL
|
2000-05-02 08:30:36 +08:00
|
|
|
ZEND_GET_MODULE(pgsql)
|
1999-04-22 10:48:28 +08:00
|
|
|
#endif
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
static int le_link, le_plink, le_result, le_lofp, le_string;
|
1999-11-20 09:04:45 +08:00
|
|
|
|
1999-11-20 08:30:08 +08:00
|
|
|
#ifdef ZTS
|
|
|
|
int pgsql_globals_id;
|
|
|
|
#else
|
2002-02-06 15:25:51 +08:00
|
|
|
php_pgsql_globals pgsql_globals;
|
1999-11-20 08:30:08 +08:00
|
|
|
#endif
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ php_pgsql_set_default_link
|
|
|
|
*/
|
2002-02-06 15:16:10 +08:00
|
|
|
static void php_pgsql_set_default_link(int id TSRMLS_DC)
|
2000-10-11 21:27:21 +08:00
|
|
|
{
|
2001-05-28 06:54:54 +08:00
|
|
|
zend_list_addref(id);
|
2001-04-05 20:29:24 +08:00
|
|
|
|
2001-05-28 06:54:54 +08:00
|
|
|
if (PGG(default_link) != -1) {
|
|
|
|
zend_list_delete(PGG(default_link));
|
|
|
|
}
|
2001-02-14 00:54:48 +08:00
|
|
|
|
2001-05-28 06:54:54 +08:00
|
|
|
PGG(default_link) = id;
|
2000-10-11 21:27:21 +08:00
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
2000-10-11 21:27:21 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ _close_pgsql_link
|
|
|
|
*/
|
2001-07-31 13:44:11 +08:00
|
|
|
static void _close_pgsql_link(zend_rsrc_list_entry *rsrc TSRMLS_DC)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-10-21 02:25:16 +08:00
|
|
|
PGconn *link = (PGconn *)rsrc->ptr;
|
2001-12-10 12:02:08 +08:00
|
|
|
PGresult *res;
|
1999-11-20 08:30:08 +08:00
|
|
|
|
2001-12-10 12:02:08 +08:00
|
|
|
while ((res = PQgetResult(link))) {
|
|
|
|
PQclear(res);
|
|
|
|
}
|
1999-04-22 10:48:28 +08:00
|
|
|
PQfinish(link);
|
1999-11-20 08:30:08 +08:00
|
|
|
PGG(num_links)--;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ _close_pgsql_plink
|
|
|
|
*/
|
2001-07-31 13:44:11 +08:00
|
|
|
static void _close_pgsql_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-10-21 02:25:16 +08:00
|
|
|
PGconn *link = (PGconn *)rsrc->ptr;
|
2001-12-10 12:02:08 +08:00
|
|
|
PGresult *res;
|
1999-11-20 08:30:08 +08:00
|
|
|
|
2001-12-10 12:02:08 +08:00
|
|
|
while ((res = PQgetResult(link))) {
|
|
|
|
PQclear(res);
|
|
|
|
}
|
1999-04-22 10:48:28 +08:00
|
|
|
PQfinish(link);
|
1999-11-20 08:30:08 +08:00
|
|
|
PGG(num_persistent)--;
|
|
|
|
PGG(num_links)--;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2002-04-06 13:52:52 +08:00
|
|
|
/* {{{ _php_pgsql_notice_handler
|
2001-06-05 21:12:10 +08:00
|
|
|
*/
|
2002-04-06 13:52:52 +08:00
|
|
|
static void _php_pgsql_notice_handler(void *resource_id, const char *message)
|
2001-02-14 04:13:14 +08:00
|
|
|
{
|
2002-04-06 13:52:52 +08:00
|
|
|
php_pgsql_notice *notice;
|
|
|
|
|
2001-07-28 19:36:37 +08:00
|
|
|
TSRMLS_FETCH();
|
2001-04-05 05:40:41 +08:00
|
|
|
if (! PGG(ignore_notices)) {
|
2002-04-06 13:52:52 +08:00
|
|
|
if (PGG(log_notices)) {
|
|
|
|
php_log_err((char *) message TSRMLS_CC);
|
2001-05-06 09:34:56 +08:00
|
|
|
}
|
2002-04-06 13:52:52 +08:00
|
|
|
notice = (php_pgsql_notice *)emalloc(sizeof(php_pgsql_notice));
|
|
|
|
notice->len = strlen(message);
|
|
|
|
notice->message = estrndup(message, notice->len);
|
|
|
|
zend_hash_index_update(&PGG(notices), *(int *)resource_id, (void **)¬ice, sizeof(php_pgsql_notice *), NULL);
|
2001-04-05 05:40:41 +08:00
|
|
|
}
|
2001-02-14 04:13:14 +08:00
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
2001-02-14 04:13:14 +08:00
|
|
|
|
2002-04-06 13:52:52 +08:00
|
|
|
#define PHP_PGSQL_NOTICE_PTR_DTOR (void (*)(void *))_php_pgsql_notice_ptr_dtor
|
|
|
|
|
|
|
|
/* {{{ _php_pgsql_notice_dtor
|
|
|
|
*/
|
|
|
|
static void _php_pgsql_notice_ptr_dtor(void **ptr)
|
|
|
|
{
|
|
|
|
php_pgsql_notice *notice = (php_pgsql_notice *)*ptr;
|
|
|
|
efree(notice->message);
|
|
|
|
efree(notice);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ _rollback_transactions
|
|
|
|
*/
|
2001-07-31 12:53:54 +08:00
|
|
|
static int _rollback_transactions(zend_rsrc_list_entry *rsrc TSRMLS_DC)
|
2001-02-14 02:28:24 +08:00
|
|
|
{
|
2001-05-28 07:26:58 +08:00
|
|
|
PGconn *link;
|
2001-12-10 12:02:08 +08:00
|
|
|
PGresult *res;
|
2002-04-06 13:52:52 +08:00
|
|
|
int orig;
|
2001-02-14 02:28:24 +08:00
|
|
|
|
2001-09-26 05:58:48 +08:00
|
|
|
if (Z_TYPE_P(rsrc) != le_plink)
|
2001-05-28 11:30:11 +08:00
|
|
|
return 0;
|
2001-05-28 07:26:58 +08:00
|
|
|
|
2001-05-28 11:30:11 +08:00
|
|
|
link = (PGconn *) rsrc->ptr;
|
2002-03-29 19:24:54 +08:00
|
|
|
|
|
|
|
if (PQ_SETNONBLOCKING(link, 0)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref("ref.pgsql" TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
|
2002-03-29 19:24:54 +08:00
|
|
|
return -1;
|
|
|
|
}
|
2001-05-28 11:30:11 +08:00
|
|
|
|
2001-12-10 12:02:08 +08:00
|
|
|
while ((res = PQgetResult(link))) {
|
|
|
|
PQclear(res);
|
|
|
|
}
|
2002-04-06 13:52:52 +08:00
|
|
|
orig = PGG(ignore_notices);
|
2001-04-05 05:40:41 +08:00
|
|
|
PGG(ignore_notices) = 1;
|
2002-03-29 19:24:54 +08:00
|
|
|
res = PQexec(link,"BEGIN;ROLLBACK;");
|
|
|
|
PQclear(res);
|
2002-04-06 13:52:52 +08:00
|
|
|
PGG(ignore_notices) = orig;
|
2001-02-14 02:28:24 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
2001-02-14 02:28:24 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ _free_ptr
|
|
|
|
*/
|
2001-07-31 13:44:11 +08:00
|
|
|
static void _free_ptr(zend_rsrc_list_entry *rsrc TSRMLS_DC)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-10-21 02:25:16 +08:00
|
|
|
pgLofp *lofp = (pgLofp *)rsrc->ptr;
|
1999-04-22 10:48:28 +08:00
|
|
|
efree(lofp);
|
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ _free_result
|
|
|
|
*/
|
2001-07-31 13:44:11 +08:00
|
|
|
static void _free_result(zend_rsrc_list_entry *rsrc TSRMLS_DC)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-10-21 02:25:16 +08:00
|
|
|
pgsql_result_handle *pg_result = (pgsql_result_handle *)rsrc->ptr;
|
2001-07-31 13:44:11 +08:00
|
|
|
|
1999-04-22 10:48:28 +08:00
|
|
|
PQclear(pg_result->result);
|
|
|
|
efree(pg_result);
|
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ PHP_INI
|
|
|
|
*/
|
2000-02-06 01:26:35 +08:00
|
|
|
PHP_INI_BEGIN()
|
2002-03-11 15:23:07 +08:00
|
|
|
STD_PHP_INI_BOOLEAN("pgsql.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_persistent, php_pgsql_globals, pgsql_globals)
|
|
|
|
STD_PHP_INI_ENTRY_EX("pgsql.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateInt, max_persistent, php_pgsql_globals, pgsql_globals, display_link_numbers)
|
|
|
|
STD_PHP_INI_ENTRY_EX("pgsql.max_links", "-1", PHP_INI_SYSTEM, OnUpdateInt, max_links, php_pgsql_globals, pgsql_globals, display_link_numbers)
|
|
|
|
STD_PHP_INI_BOOLEAN("pgsql.auto_reset_persistent", "0", PHP_INI_SYSTEM, OnUpdateBool, auto_reset_persistent, php_pgsql_globals, pgsql_globals)
|
2002-04-06 13:52:52 +08:00
|
|
|
STD_PHP_INI_BOOLEAN("pgsql.ignore_notice", "0", PHP_INI_ALL, OnUpdateBool, ignore_notices, php_pgsql_globals, pgsql_globals)
|
|
|
|
STD_PHP_INI_BOOLEAN("pgsql.log_notice", "0", PHP_INI_ALL, OnUpdateBool, log_notices, php_pgsql_globals, pgsql_globals)
|
2000-02-06 01:26:35 +08:00
|
|
|
PHP_INI_END()
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
2000-02-06 01:26:35 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ php_pgsql_init_globals
|
|
|
|
*/
|
2001-07-28 19:36:37 +08:00
|
|
|
static void php_pgsql_init_globals(php_pgsql_globals *pgsql_globals_p TSRMLS_DC)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-11-20 09:04:45 +08:00
|
|
|
PGG(num_persistent) = 0;
|
2002-04-06 13:52:52 +08:00
|
|
|
/* Initilize notice message hash at MINIT only */
|
|
|
|
zend_hash_init_ex(&PGG(notices), 0, NULL, PHP_PGSQL_NOTICE_PTR_DTOR, 1, 0);
|
1999-11-20 09:04:45 +08:00
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
1999-11-20 09:04:45 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ PHP_MINIT_FUNCTION
|
|
|
|
*/
|
1999-11-20 09:04:45 +08:00
|
|
|
PHP_MINIT_FUNCTION(pgsql)
|
|
|
|
{
|
|
|
|
#ifdef ZTS
|
2001-07-27 18:16:41 +08:00
|
|
|
ts_allocate_id(&pgsql_globals_id, sizeof(php_pgsql_globals), (ts_allocate_ctor) php_pgsql_init_globals, NULL);
|
1999-11-20 09:04:45 +08:00
|
|
|
#else
|
2001-07-28 19:36:37 +08:00
|
|
|
php_pgsql_init_globals(&pgsql_globals TSRMLS_CC);
|
1999-11-20 09:04:45 +08:00
|
|
|
#endif
|
2000-02-06 01:26:35 +08:00
|
|
|
|
|
|
|
REGISTER_INI_ENTRIES();
|
1999-11-20 09:04:45 +08:00
|
|
|
|
2000-10-26 01:44:02 +08:00
|
|
|
le_link = zend_register_list_destructors_ex(_close_pgsql_link, NULL, "pgsql link", module_number);
|
|
|
|
le_plink = zend_register_list_destructors_ex(NULL, _close_pgsql_plink, "pgsql link persistent", module_number);
|
|
|
|
le_result = zend_register_list_destructors_ex(_free_result, NULL, "pgsql result", module_number);
|
|
|
|
le_lofp = zend_register_list_destructors_ex(_free_ptr, NULL, "pgsql large object", module_number);
|
|
|
|
le_string = zend_register_list_destructors_ex(_free_ptr, NULL, "pgsql string", module_number);
|
2002-03-11 15:19:57 +08:00
|
|
|
/* For pg_fetch_array() */
|
1999-07-17 01:27:42 +08:00
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_ASSOC", PGSQL_ASSOC, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_NUM", PGSQL_NUM, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_BOTH", PGSQL_BOTH, CONST_CS | CONST_PERSISTENT);
|
2002-03-11 15:19:57 +08:00
|
|
|
/* For pg_connection_status() */
|
2001-12-10 12:02:08 +08:00
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_BAD", CONNECTION_BAD, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_OK", CONNECTION_OK, CONST_CS | CONST_PERSISTENT);
|
2002-03-11 15:19:57 +08:00
|
|
|
/* For lo_seek() */
|
2001-12-17 08:24:59 +08:00
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_SEEK_SET", SEEK_SET, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_SEEK_CUR", SEEK_CUR, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_SEEK_END", SEEK_END, CONST_CS | CONST_PERSISTENT);
|
2002-04-08 08:43:58 +08:00
|
|
|
/* For pg_result_status() return value type */
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_STATUS_LONG", PGSQL_STATUS_LONG, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_STATUS_STRING", PGSQL_STATUS_STRING, CONST_CS | CONST_PERSISTENT);
|
|
|
|
/* For pg_result_status() return value */
|
2001-12-17 08:24:59 +08:00
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_EMPTY_QUERY", PGRES_EMPTY_QUERY, CONST_CS | CONST_PERSISTENT);
|
2002-01-21 08:36:22 +08:00
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_COMMAND_OK", PGRES_COMMAND_OK, CONST_CS | CONST_PERSISTENT);
|
2001-12-17 08:24:59 +08:00
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_TUPLES_OK", PGRES_TUPLES_OK, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_COPY_OUT", PGRES_COPY_OUT, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_COPY_IN", PGRES_COPY_IN, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_BAD_RESPONSE", PGRES_BAD_RESPONSE, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_NONFATAL_ERROR", PGRES_NONFATAL_ERROR, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_FATAL_ERROR", PGRES_FATAL_ERROR, CONST_CS | CONST_PERSISTENT);
|
2002-04-23 11:42:26 +08:00
|
|
|
/* pg_convert options */
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_CONV_IGNORE_DEFAULT", PGSQL_CONV_IGNORE_DEFAULT, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_CONV_FORCE_NULL", PGSQL_CONV_FORCE_NULL, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_CONV_IGNORE_NOT_NULL", PGSQL_CONV_IGNORE_NOT_NULL, CONST_CS | CONST_PERSISTENT);
|
|
|
|
/* pg_insert/update/delete/select options */
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_DML_NO_CONV", PGSQL_DML_NO_CONV, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_DML_EXEC", PGSQL_DML_EXEC, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_DML_ASYNC", PGSQL_DML_ASYNC, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PGSQL_DML_STRING", PGSQL_DML_STRING, CONST_CS | CONST_PERSISTENT);
|
1999-04-22 10:48:28 +08:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ PHP_MSHUTDOWN_FUNCTION
|
|
|
|
*/
|
2000-02-06 01:26:35 +08:00
|
|
|
PHP_MSHUTDOWN_FUNCTION(pgsql)
|
|
|
|
{
|
|
|
|
UNREGISTER_INI_ENTRIES();
|
2002-04-08 09:37:38 +08:00
|
|
|
|
2000-02-06 01:26:35 +08:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
2000-02-06 01:26:35 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ PHP_RINIT_FUNCTION
|
|
|
|
*/
|
1999-12-18 19:38:04 +08:00
|
|
|
PHP_RINIT_FUNCTION(pgsql)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-11-20 08:30:08 +08:00
|
|
|
PGG(default_link)=-1;
|
|
|
|
PGG(num_links) = PGG(num_persistent);
|
1999-04-22 10:48:28 +08:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ PHP_RSHUTDOWN_FUNCTION
|
|
|
|
*/
|
2001-02-14 02:28:24 +08:00
|
|
|
PHP_RSHUTDOWN_FUNCTION(pgsql)
|
|
|
|
{
|
2002-04-06 13:52:52 +08:00
|
|
|
/* clean up notice messages */
|
|
|
|
zend_hash_clean(&PGG(notices));
|
|
|
|
/* clean up persistent connection */
|
2001-07-31 12:53:54 +08:00
|
|
|
zend_hash_apply(&EG(persistent_list), (apply_func_t) _rollback_transactions TSRMLS_CC);
|
2001-02-14 02:28:24 +08:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
2001-02-14 02:28:24 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ PHP_MINFO_FUNCTION
|
|
|
|
*/
|
2000-05-24 14:48:04 +08:00
|
|
|
PHP_MINFO_FUNCTION(pgsql)
|
|
|
|
{
|
2002-04-08 09:37:38 +08:00
|
|
|
char buf[256];
|
2000-05-24 14:48:04 +08:00
|
|
|
|
|
|
|
php_info_print_table_start();
|
|
|
|
php_info_print_table_header(2, "PostgreSQL Support", "enabled");
|
2002-03-31 09:45:22 +08:00
|
|
|
#if HAVE_PG_CONFIG_H
|
2002-03-31 09:18:32 +08:00
|
|
|
php_info_print_table_row(2, "PostgreSQL(libpq) Version", PG_VERSION);
|
2002-03-31 09:45:22 +08:00
|
|
|
#ifdef MULTIBYTE
|
|
|
|
php_info_print_table_row(2, "Multibyte charater support", "enabled");
|
|
|
|
#else
|
|
|
|
php_info_print_table_row(2, "Multibyte charater support", "disabled");
|
|
|
|
#endif
|
|
|
|
#ifdef USE_SSL
|
|
|
|
php_info_print_table_row(2, "SSL support", "enabled");
|
|
|
|
#else
|
|
|
|
php_info_print_table_row(2, "SSL support", "disabled");
|
|
|
|
#endif
|
|
|
|
#endif /* HAVE_PG_CONFIG_H */
|
2000-05-24 14:48:04 +08:00
|
|
|
sprintf(buf, "%ld", PGG(num_persistent));
|
|
|
|
php_info_print_table_row(2, "Active Persistent Links", buf);
|
|
|
|
sprintf(buf, "%ld", PGG(num_links));
|
|
|
|
php_info_print_table_row(2, "Active Links", buf);
|
|
|
|
php_info_print_table_end();
|
|
|
|
|
|
|
|
DISPLAY_INI_ENTRIES();
|
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
2001-04-05 05:40:41 +08:00
|
|
|
|
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ php_pgsql_do_connect
|
|
|
|
*/
|
2002-02-06 15:16:10 +08:00
|
|
|
static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
|
|
|
char *host=NULL,*port=NULL,*options=NULL,*tty=NULL,*dbname=NULL,*connstring=NULL;
|
|
|
|
PGconn *pgsql;
|
2002-04-21 19:29:17 +08:00
|
|
|
smart_str str = {0};
|
|
|
|
zval **args[5];
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() == 2 || ZEND_NUM_ARGS() > 5
|
|
|
|
|| zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
}
|
|
|
|
|
|
|
|
smart_str_appends(&str, "pgsql");
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2002-04-21 19:29:17 +08:00
|
|
|
for (i = 0; i < ZEND_NUM_ARGS(); i++) {
|
|
|
|
convert_to_string_ex(args[i]);
|
|
|
|
smart_str_appendc(&str, '_');
|
|
|
|
smart_str_appendl(&str, Z_STRVAL_PP(args[i]), Z_STRLEN_PP(args[i]));
|
|
|
|
}
|
|
|
|
|
|
|
|
smart_str_0(&str);
|
|
|
|
|
|
|
|
if (ZEND_NUM_ARGS() == 1) { /* new style, using connection string */
|
|
|
|
connstring = Z_STRVAL_PP(args[0]);
|
|
|
|
} else {
|
|
|
|
host = Z_STRVAL_PP(args[0]);
|
|
|
|
port = Z_STRVAL_PP(args[1]);
|
|
|
|
dbname = Z_STRVAL_PP(args[ZEND_NUM_ARGS()-1]);
|
|
|
|
|
|
|
|
switch (ZEND_NUM_ARGS()) {
|
|
|
|
case 5:
|
|
|
|
tty = Z_STRVAL_PP(args[3]);
|
|
|
|
/* fall through */
|
|
|
|
case 4:
|
|
|
|
options = Z_STRVAL_PP(args[2]);
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
2002-03-11 15:23:07 +08:00
|
|
|
}
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
|
2001-07-14 01:13:00 +08:00
|
|
|
if (persistent && PGG(allow_persistent)) {
|
1999-04-22 10:48:28 +08:00
|
|
|
list_entry *le;
|
|
|
|
|
|
|
|
/* try to find if we already have this link in our persistent list */
|
2002-04-21 19:29:17 +08:00
|
|
|
if (zend_hash_find(&EG(persistent_list), str.c, str.len+1, (void **) &le)==FAILURE) { /* we don't */
|
1999-04-22 10:48:28 +08:00
|
|
|
list_entry new_le;
|
|
|
|
|
1999-11-20 08:30:08 +08:00
|
|
|
if (PGG(max_links)!=-1 && PGG(num_links)>=PGG(max_links)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
|
|
|
"Cannot create new link. Too many open links (%d)", PGG(num_links));
|
2002-04-21 19:29:17 +08:00
|
|
|
goto err;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
1999-11-20 08:30:08 +08:00
|
|
|
if (PGG(max_persistent)!=-1 && PGG(num_persistent)>=PGG(max_persistent)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
|
|
|
"Cannot create new link. Too many open persistent links (%d)", PGG(num_persistent));
|
2002-04-21 19:29:17 +08:00
|
|
|
goto err;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* create the link */
|
|
|
|
if (connstring) {
|
|
|
|
pgsql=PQconnectdb(connstring);
|
|
|
|
} else {
|
|
|
|
pgsql=PQsetdb(host,port,options,tty,dbname);
|
|
|
|
}
|
|
|
|
if (pgsql==NULL || PQstatus(pgsql)==CONNECTION_BAD) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
|
|
|
"Unable to connect to PostgreSQL server: %s", PQerrorMessage(pgsql));
|
2001-04-30 01:33:11 +08:00
|
|
|
if (pgsql) {
|
|
|
|
PQfinish(pgsql);
|
|
|
|
}
|
2002-04-21 19:29:17 +08:00
|
|
|
goto err;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* hash it up */
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_TYPE(new_le) = le_plink;
|
1999-04-22 10:48:28 +08:00
|
|
|
new_le.ptr = pgsql;
|
2002-04-21 19:29:17 +08:00
|
|
|
if (zend_hash_update(&EG(persistent_list), str.c, str.len+1, (void *) &new_le, sizeof(list_entry), NULL)==FAILURE) {
|
|
|
|
goto err;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
1999-11-20 08:30:08 +08:00
|
|
|
PGG(num_links)++;
|
|
|
|
PGG(num_persistent)++;
|
1999-04-22 10:48:28 +08:00
|
|
|
} else { /* we do */
|
2001-09-26 05:58:48 +08:00
|
|
|
if (Z_TYPE_P(le) != le_plink) {
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
/* ensure that the link did not die */
|
2002-01-25 08:43:50 +08:00
|
|
|
if (PGG(auto_reset_persistent)) {
|
2002-01-24 17:27:43 +08:00
|
|
|
/* need to send & get something from backend to
|
|
|
|
make sure we catch CONNECTION_BAD everytime */
|
|
|
|
PGresult *pg_result;
|
|
|
|
pg_result = PQexec(le->ptr, "select 1");
|
|
|
|
PQclear(pg_result);
|
|
|
|
}
|
1999-04-22 10:48:28 +08:00
|
|
|
if (PQstatus(le->ptr)==CONNECTION_BAD) { /* the link died */
|
2002-01-24 17:27:43 +08:00
|
|
|
if (le->ptr == NULL) {
|
|
|
|
if (connstring) {
|
|
|
|
le->ptr=PQconnectdb(connstring);
|
|
|
|
} else {
|
|
|
|
le->ptr=PQsetdb(host,port,options,tty,dbname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
PQreset(le->ptr);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
if (le->ptr==NULL || PQstatus(le->ptr)==CONNECTION_BAD) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING,"PostgreSQL link lost, unable to reconnect");
|
2002-04-21 19:29:17 +08:00
|
|
|
zend_hash_del(&EG(persistent_list),str.c,str.len+1);
|
|
|
|
goto err;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
pgsql = (PGconn *) le->ptr;
|
|
|
|
}
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_REGISTER_RESOURCE(return_value, pgsql, le_plink);
|
1999-04-22 10:48:28 +08:00
|
|
|
} else {
|
|
|
|
list_entry *index_ptr,new_index_ptr;
|
|
|
|
|
|
|
|
/* first we check the hash for the hashed_details key. if it exists,
|
|
|
|
* it should point us to the right offset where the actual pgsql link sits.
|
|
|
|
* if it doesn't, open a new pgsql link, add it to the resource list,
|
|
|
|
* and add a pointer to it with hashed_details as the key.
|
|
|
|
*/
|
2002-04-21 19:29:17 +08:00
|
|
|
if (zend_hash_find(&EG(regular_list),str.c,str.len+1,(void **) &index_ptr)==SUCCESS) {
|
1999-04-22 10:48:28 +08:00
|
|
|
int type,link;
|
|
|
|
void *ptr;
|
|
|
|
|
2001-09-26 05:58:48 +08:00
|
|
|
if (Z_TYPE_P(index_ptr) != le_index_ptr) {
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2002-04-21 19:29:17 +08:00
|
|
|
link = (int) (long) index_ptr->ptr; /* XXX: bogus? cast */
|
1999-12-18 03:51:39 +08:00
|
|
|
ptr = zend_list_find(link,&type); /* check if the link is still there */
|
1999-11-20 09:04:45 +08:00
|
|
|
if (ptr && (type==le_link || type==le_plink)) {
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_LVAL_P(return_value) = link;
|
2001-02-15 10:15:36 +08:00
|
|
|
zend_list_addref(link);
|
2002-02-06 15:16:10 +08:00
|
|
|
php_pgsql_set_default_link(link TSRMLS_CC);
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_TYPE_P(return_value) = IS_RESOURCE;
|
2002-04-21 19:29:17 +08:00
|
|
|
goto cleanup;
|
1999-04-22 10:48:28 +08:00
|
|
|
} else {
|
2002-04-21 19:29:17 +08:00
|
|
|
zend_hash_del(&EG(regular_list),str.c,str.len+1);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
}
|
1999-11-20 08:30:08 +08:00
|
|
|
if (PGG(max_links)!=-1 && PGG(num_links)>=PGG(max_links)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create new link. Too many open links (%d)", PGG(num_links));
|
2002-04-21 19:29:17 +08:00
|
|
|
goto err;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
if (connstring) {
|
2000-05-25 15:51:40 +08:00
|
|
|
pgsql = PQconnectdb(connstring);
|
1999-04-22 10:48:28 +08:00
|
|
|
} else {
|
2000-05-25 15:51:40 +08:00
|
|
|
pgsql = PQsetdb(host,port,options,tty,dbname);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
if (pgsql==NULL || PQstatus(pgsql)==CONNECTION_BAD) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to PostgreSQL server: %s", PQerrorMessage(pgsql));
|
2002-04-21 19:29:17 +08:00
|
|
|
goto err;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* add it to the list */
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_REGISTER_RESOURCE(return_value, pgsql, le_link);
|
1999-04-22 10:48:28 +08:00
|
|
|
|
|
|
|
/* add it to the hash */
|
2001-09-26 05:58:48 +08:00
|
|
|
new_index_ptr.ptr = (void *) Z_LVAL_P(return_value);
|
|
|
|
Z_TYPE(new_index_ptr) = le_index_ptr;
|
2002-04-21 19:29:17 +08:00
|
|
|
if (zend_hash_update(&EG(regular_list),str.c,str.len+1,(void *) &new_index_ptr, sizeof(list_entry), NULL)==FAILURE) {
|
|
|
|
goto err;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
1999-11-20 08:30:08 +08:00
|
|
|
PGG(num_links)++;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2002-04-06 13:52:52 +08:00
|
|
|
/* set notice processer */
|
|
|
|
if (! PGG(ignore_notices) && Z_TYPE_P(return_value) == IS_RESOURCE) {
|
|
|
|
PQsetNoticeProcessor(pgsql, _php_pgsql_notice_handler, (void *)&Z_RESVAL_P(return_value));
|
|
|
|
}
|
2002-02-06 15:16:10 +08:00
|
|
|
php_pgsql_set_default_link(Z_LVAL_P(return_value) TSRMLS_CC);
|
2002-04-21 19:29:17 +08:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
smart_str_free(&str);
|
|
|
|
return;
|
|
|
|
|
|
|
|
err:
|
|
|
|
smart_str_free(&str);
|
|
|
|
RETURN_FALSE;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2002-02-06 15:16:10 +08:00
|
|
|
#if 0
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ php_pgsql_get_default_link
|
|
|
|
*/
|
2002-02-06 15:16:10 +08:00
|
|
|
static int php_pgsql_get_default_link(INTERNAL_FUNCTION_PARAMETERS)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-11-20 08:30:08 +08:00
|
|
|
if (PGG(default_link)==-1) { /* no link opened yet, implicitly open one */
|
1999-07-23 07:54:54 +08:00
|
|
|
ht = 0;
|
1999-12-18 19:38:04 +08:00
|
|
|
php_pgsql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
1999-11-20 08:30:08 +08:00
|
|
|
return PGG(default_link);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
2002-02-06 15:16:10 +08:00
|
|
|
#endif
|
1999-07-23 07:54:54 +08:00
|
|
|
|
2001-12-10 14:14:03 +08:00
|
|
|
/* {{{ proto resource pg_connect([string connection_string] | [string host, string port [, string options [, string tty,]] string database)
|
1999-04-22 10:48:28 +08:00
|
|
|
Open a PostgreSQL connection */
|
1999-12-20 06:44:55 +08:00
|
|
|
PHP_FUNCTION(pg_connect)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-12-18 19:38:04 +08:00
|
|
|
php_pgsql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-10 14:14:03 +08:00
|
|
|
/* {{{ proto resource pg_pconnect([string connection_string] | [string host, string port [, string options [, string tty,]] string database)
|
1999-04-22 10:48:28 +08:00
|
|
|
Open a persistent PostgreSQL connection */
|
1999-12-20 06:44:55 +08:00
|
|
|
PHP_FUNCTION(pg_pconnect)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-12-18 19:38:04 +08:00
|
|
|
php_pgsql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,1);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-10 14:14:03 +08:00
|
|
|
/* {{{ proto bool pg_close([resource connection])
|
1999-04-22 10:48:28 +08:00
|
|
|
Close a PostgreSQL connection */
|
1999-12-20 06:44:55 +08:00
|
|
|
PHP_FUNCTION(pg_close)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-07-29 14:07:26 +08:00
|
|
|
zval **pgsql_link = NULL;
|
2001-04-05 20:29:24 +08:00
|
|
|
int id;
|
1999-04-22 10:48:28 +08:00
|
|
|
PGconn *pgsql;
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
switch (ZEND_NUM_ARGS()) {
|
1999-04-22 10:48:28 +08:00
|
|
|
case 0:
|
1999-11-20 08:30:08 +08:00
|
|
|
id = PGG(default_link);
|
2000-07-29 14:07:26 +08:00
|
|
|
CHECK_DEFAULT_LINK(id);
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
|
|
|
case 1:
|
2000-05-25 15:51:40 +08:00
|
|
|
if (zend_get_parameters_ex(1, &pgsql_link)==FAILURE) {
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2000-11-03 10:46:49 +08:00
|
|
|
id = -1;
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
2000-11-03 10:46:49 +08:00
|
|
|
|
|
|
|
if (id==-1) { /* explicit resource number */
|
|
|
|
zend_list_delete(Z_RESVAL_PP(pgsql_link));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (id!=-1
|
|
|
|
|| (pgsql_link && Z_RESVAL_PP(pgsql_link)==PGG(default_link))) {
|
2001-03-26 16:00:43 +08:00
|
|
|
zend_list_delete(PGG(default_link));
|
2000-11-03 10:46:49 +08:00
|
|
|
PGG(default_link) = -1;
|
2000-11-03 08:51:53 +08:00
|
|
|
}
|
|
|
|
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
|
1999-12-18 19:38:04 +08:00
|
|
|
#define PHP_PG_DBNAME 1
|
|
|
|
#define PHP_PG_ERROR_MESSAGE 2
|
|
|
|
#define PHP_PG_OPTIONS 3
|
|
|
|
#define PHP_PG_PORT 4
|
|
|
|
#define PHP_PG_TTY 5
|
|
|
|
#define PHP_PG_HOST 6
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ php_pgsql_get_link_info
|
|
|
|
*/
|
2002-02-06 15:16:10 +08:00
|
|
|
static void php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-07-29 14:07:26 +08:00
|
|
|
zval **pgsql_link = NULL;
|
2000-05-25 15:51:40 +08:00
|
|
|
int id = -1;
|
1999-04-22 10:48:28 +08:00
|
|
|
PGconn *pgsql;
|
1999-11-20 08:30:08 +08:00
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
switch(ZEND_NUM_ARGS()) {
|
1999-04-22 10:48:28 +08:00
|
|
|
case 0:
|
1999-11-20 08:30:08 +08:00
|
|
|
id = PGG(default_link);
|
2000-07-29 14:07:26 +08:00
|
|
|
CHECK_DEFAULT_LINK(id);
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
|
|
|
case 1:
|
2000-05-25 15:51:40 +08:00
|
|
|
if (zend_get_parameters_ex(1, &pgsql_link)==FAILURE) {
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
1999-04-22 10:48:28 +08:00
|
|
|
switch(entry_type) {
|
1999-12-18 19:38:04 +08:00
|
|
|
case PHP_PG_DBNAME:
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_STRVAL_P(return_value) = PQdb(pgsql);
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
1999-12-18 19:38:04 +08:00
|
|
|
case PHP_PG_ERROR_MESSAGE:
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_STRVAL_P(return_value) = PQerrorMessage(pgsql);
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
1999-12-18 19:38:04 +08:00
|
|
|
case PHP_PG_OPTIONS:
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_STRVAL_P(return_value) = PQoptions(pgsql);
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
1999-12-18 19:38:04 +08:00
|
|
|
case PHP_PG_PORT:
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_STRVAL_P(return_value) = PQport(pgsql);
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
1999-12-18 19:38:04 +08:00
|
|
|
case PHP_PG_TTY:
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_STRVAL_P(return_value) = PQtty(pgsql);
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
1999-12-18 19:38:04 +08:00
|
|
|
case PHP_PG_HOST:
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_STRVAL_P(return_value) = PQhost(pgsql);
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
|
|
|
Z_STRVAL_P(return_value) = (char *) estrdup(Z_STRVAL_P(return_value));
|
|
|
|
Z_TYPE_P(return_value) = IS_STRING;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-12-10 14:14:03 +08:00
|
|
|
/* {{{ proto string pg_dbname([resource connection])
|
1999-04-22 10:48:28 +08:00
|
|
|
Get the database name */
|
1999-12-20 06:44:55 +08:00
|
|
|
PHP_FUNCTION(pg_dbname)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-12-18 19:38:04 +08:00
|
|
|
php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_DBNAME);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto string pg_last_error([resource connection])
|
1999-04-22 10:48:28 +08:00
|
|
|
Get the error message string */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_last_error)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-12-18 19:38:04 +08:00
|
|
|
php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_ERROR_MESSAGE);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-10 14:14:03 +08:00
|
|
|
/* {{{ proto string pg_options([resource connection])
|
1999-04-22 10:48:28 +08:00
|
|
|
Get the options associated with the connection */
|
1999-12-20 06:44:55 +08:00
|
|
|
PHP_FUNCTION(pg_options)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-12-18 19:38:04 +08:00
|
|
|
php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_OPTIONS);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-10 14:14:03 +08:00
|
|
|
/* {{{ proto int pg_port([resource connection])
|
1999-04-22 10:48:28 +08:00
|
|
|
Return the port number associated with the connection */
|
1999-12-20 06:44:55 +08:00
|
|
|
PHP_FUNCTION(pg_port)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-12-18 19:38:04 +08:00
|
|
|
php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_PORT);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-10 14:14:03 +08:00
|
|
|
/* {{{ proto string pg_tty([resource connection])
|
1999-04-22 10:48:28 +08:00
|
|
|
Return the tty name associated with the connection */
|
1999-12-20 06:44:55 +08:00
|
|
|
PHP_FUNCTION(pg_tty)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-12-18 19:38:04 +08:00
|
|
|
php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_TTY);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-10 14:14:03 +08:00
|
|
|
/* {{{ proto string pg_host([resource connection])
|
1999-04-22 10:48:28 +08:00
|
|
|
Returns the host name associated with the connection */
|
1999-12-20 06:44:55 +08:00
|
|
|
PHP_FUNCTION(pg_host)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-12-18 19:38:04 +08:00
|
|
|
php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_HOST);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto resource pg_query([resource connection,] string query)
|
1999-04-22 10:48:28 +08:00
|
|
|
Execute a query */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_query)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-07-29 14:07:26 +08:00
|
|
|
zval **query, **pgsql_link = NULL;
|
2000-05-25 15:51:40 +08:00
|
|
|
int id = -1;
|
2001-12-10 12:02:08 +08:00
|
|
|
int leftover = 0;
|
1999-04-22 10:48:28 +08:00
|
|
|
PGconn *pgsql;
|
|
|
|
PGresult *pgsql_result;
|
2000-05-25 15:51:40 +08:00
|
|
|
ExecStatusType status;
|
1999-04-22 10:48:28 +08:00
|
|
|
pgsql_result_handle *pg_result;
|
2001-12-10 12:02:08 +08:00
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
switch(ZEND_NUM_ARGS()) {
|
1999-04-22 10:48:28 +08:00
|
|
|
case 1:
|
2000-05-25 15:51:40 +08:00
|
|
|
if (zend_get_parameters_ex(1, &query)==FAILURE) {
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
1999-11-20 08:30:08 +08:00
|
|
|
id = PGG(default_link);
|
2000-07-29 14:07:26 +08:00
|
|
|
CHECK_DEFAULT_LINK(id);
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
|
|
|
case 2:
|
2000-05-25 15:51:40 +08:00
|
|
|
if (zend_get_parameters_ex(2, &pgsql_link, &query)==FAILURE) {
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
|
|
|
convert_to_string_ex(query);
|
2002-03-29 19:24:54 +08:00
|
|
|
if (PQ_SETNONBLOCKING(pgsql, 0)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to blocking mode");
|
2002-03-29 19:24:54 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2001-12-10 12:02:08 +08:00
|
|
|
while ((pgsql_result = PQgetResult(pgsql))) {
|
|
|
|
PQclear(pgsql_result);
|
|
|
|
leftover = 1;
|
|
|
|
}
|
|
|
|
if (leftover) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found results on this connection. Use pg_get_result() to get results");
|
2001-12-10 12:02:08 +08:00
|
|
|
}
|
2000-05-25 15:51:40 +08:00
|
|
|
pgsql_result = PQexec(pgsql, Z_STRVAL_PP(query));
|
1999-04-22 10:48:28 +08:00
|
|
|
|
|
|
|
if (pgsql_result) {
|
|
|
|
status = PQresultStatus(pgsql_result);
|
|
|
|
} else {
|
|
|
|
status = (ExecStatusType) PQstatus(pgsql);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (status) {
|
|
|
|
case PGRES_EMPTY_QUERY:
|
|
|
|
case PGRES_BAD_RESPONSE:
|
|
|
|
case PGRES_NONFATAL_ERROR:
|
|
|
|
case PGRES_FATAL_ERROR:
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed: %s", PQerrorMessage(pgsql));
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
break;
|
|
|
|
case PGRES_COMMAND_OK: /* successful command that did not return rows */
|
|
|
|
default:
|
|
|
|
if (pgsql_result) {
|
|
|
|
pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle));
|
|
|
|
pg_result->conn = pgsql;
|
|
|
|
pg_result->result = pgsql_result;
|
2001-06-20 02:10:08 +08:00
|
|
|
pg_result->row = -1;
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result);
|
1999-04-22 10:48:28 +08:00
|
|
|
} else {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
2001-06-05 21:12:10 +08:00
|
|
|
|
1999-12-18 19:38:04 +08:00
|
|
|
#define PHP_PG_NUM_ROWS 1
|
|
|
|
#define PHP_PG_NUM_FIELDS 2
|
|
|
|
#define PHP_PG_CMD_TUPLES 3
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ php_pgsql_get_result_info
|
|
|
|
*/
|
2002-02-06 15:16:10 +08:00
|
|
|
static void php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-05-25 15:51:40 +08:00
|
|
|
zval **result;
|
1999-04-22 10:48:28 +08:00
|
|
|
PGresult *pgsql_result;
|
|
|
|
pgsql_result_handle *pg_result;
|
1999-11-20 08:30:08 +08:00
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &result)==FAILURE) {
|
1999-04-22 10:48:28 +08:00
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
}
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, result, -1, "PostgreSQL result", le_result);
|
1999-04-22 10:48:28 +08:00
|
|
|
|
|
|
|
pgsql_result = pg_result->result;
|
2001-12-17 08:24:59 +08:00
|
|
|
|
1999-04-22 10:48:28 +08:00
|
|
|
switch (entry_type) {
|
1999-12-18 19:38:04 +08:00
|
|
|
case PHP_PG_NUM_ROWS:
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_LVAL_P(return_value) = PQntuples(pgsql_result);
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
1999-12-18 19:38:04 +08:00
|
|
|
case PHP_PG_NUM_FIELDS:
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_LVAL_P(return_value) = PQnfields(pgsql_result);
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
1999-12-18 19:38:04 +08:00
|
|
|
case PHP_PG_CMD_TUPLES:
|
1999-04-22 10:48:28 +08:00
|
|
|
#if HAVE_PQCMDTUPLES
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_LVAL_P(return_value) = atoi(PQcmdTuples(pgsql_result));
|
1999-04-22 10:48:28 +08:00
|
|
|
#else
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not supportted under this build");
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_LVAL_P(return_value) = 0;
|
1999-04-22 10:48:28 +08:00
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_TYPE_P(return_value) = IS_LONG;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto int pg_num_rows(resource result)
|
1999-04-22 10:48:28 +08:00
|
|
|
Return the number of rows in the result */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_num_rows)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-12-18 19:38:04 +08:00
|
|
|
php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_NUM_ROWS);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto int pg_num_fields(resource result)
|
1999-04-22 10:48:28 +08:00
|
|
|
Return the number of fields in the result */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_num_fields)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-12-18 19:38:04 +08:00
|
|
|
php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_NUM_FIELDS);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto int pg_affected_rows(resource result)
|
1999-04-22 10:48:28 +08:00
|
|
|
Returns the number of affected tuples */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_affected_rows)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-12-18 19:38:04 +08:00
|
|
|
php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_CMD_TUPLES);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-10 14:14:03 +08:00
|
|
|
/* {{{ proto string pg_last_notice(resource connection)
|
2001-05-06 14:33:48 +08:00
|
|
|
Returns the last notice set by the backend */
|
2001-06-04 16:06:07 +08:00
|
|
|
PHP_FUNCTION(pg_last_notice)
|
|
|
|
{
|
2002-04-06 13:52:52 +08:00
|
|
|
zval *pgsql_link;
|
|
|
|
PGconn *pg_link;
|
|
|
|
int id = -1;
|
|
|
|
php_pgsql_notice **notice;
|
|
|
|
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r",
|
|
|
|
&pgsql_link) == FAILURE) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* Just to check if user passed valid resoruce */
|
|
|
|
ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
|
|
|
if (zend_hash_index_find(&PGG(notices), Z_RESVAL_P(pgsql_link), (void **)¬ice) == FAILURE) {
|
2001-09-27 05:44:48 +08:00
|
|
|
RETURN_FALSE;
|
2001-05-06 09:34:56 +08:00
|
|
|
}
|
2002-04-06 13:52:52 +08:00
|
|
|
RETURN_STRINGL((*notice)->message, (*notice)->len, 1);
|
2001-05-06 09:34:56 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ get_field_name
|
|
|
|
*/
|
2002-02-06 15:16:10 +08:00
|
|
|
static char *get_field_name(PGconn *pgsql, Oid oid, HashTable *list TSRMLS_DC)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
|
|
|
PGresult *result;
|
2002-04-21 17:46:29 +08:00
|
|
|
smart_str str = {0};
|
1999-04-22 10:48:28 +08:00
|
|
|
list_entry *field_type;
|
|
|
|
char *ret=NULL;
|
1999-11-20 08:30:08 +08:00
|
|
|
|
1999-04-22 10:48:28 +08:00
|
|
|
/* try to lookup the type in the resource list */
|
2002-04-21 17:46:29 +08:00
|
|
|
smart_str_appends(&str, "pgsql_oid_");
|
|
|
|
smart_str_append_unsigned(&str, oid);
|
|
|
|
smart_str_0(&str);
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2002-04-21 17:46:29 +08:00
|
|
|
if (zend_hash_find(list,str.c,str.len+1,(void **) &field_type)==SUCCESS) {
|
1999-04-22 10:48:28 +08:00
|
|
|
ret = estrdup((char *)field_type->ptr);
|
|
|
|
} else { /* hash all oid's */
|
|
|
|
int i,num_rows;
|
|
|
|
int oid_offset,name_offset;
|
2002-04-20 10:31:48 +08:00
|
|
|
char *tmp_oid, *end_ptr, *tmp_name;
|
1999-04-22 10:48:28 +08:00
|
|
|
list_entry new_oid_entry;
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
if ((result = PQexec(pgsql,"select oid,typname from pg_type")) == NULL) {
|
2002-04-21 17:46:29 +08:00
|
|
|
smart_str_free(&str);
|
1999-04-22 10:48:28 +08:00
|
|
|
return empty_string;
|
|
|
|
}
|
2000-05-25 15:51:40 +08:00
|
|
|
num_rows = PQntuples(result);
|
1999-04-22 10:48:28 +08:00
|
|
|
oid_offset = PQfnumber(result,"oid");
|
|
|
|
name_offset = PQfnumber(result,"typname");
|
|
|
|
|
|
|
|
for (i=0; i<num_rows; i++) {
|
2000-05-25 15:51:40 +08:00
|
|
|
if ((tmp_oid = PQgetvalue(result,i,oid_offset))==NULL) {
|
1999-04-22 10:48:28 +08:00
|
|
|
continue;
|
|
|
|
}
|
2002-04-21 17:46:29 +08:00
|
|
|
|
|
|
|
str.len = 0;
|
|
|
|
smart_str_appends(&str, "pgsql_oid_");
|
|
|
|
smart_str_appends(&str, tmp_oid);
|
|
|
|
smart_str_0(&str);
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
if ((tmp_name = PQgetvalue(result,i,name_offset))==NULL) {
|
1999-04-22 10:48:28 +08:00
|
|
|
continue;
|
|
|
|
}
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_TYPE(new_oid_entry) = le_string;
|
1999-04-22 10:48:28 +08:00
|
|
|
new_oid_entry.ptr = estrdup(tmp_name);
|
2002-04-21 17:46:29 +08:00
|
|
|
zend_hash_update(list,str.c,str.len+1,(void *) &new_oid_entry, sizeof(list_entry), NULL);
|
2002-04-20 10:31:48 +08:00
|
|
|
if (!ret && strtoul(tmp_oid, &end_ptr, 10)==oid) {
|
1999-04-22 10:48:28 +08:00
|
|
|
ret = estrdup(tmp_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-04-21 17:46:29 +08:00
|
|
|
|
|
|
|
smart_str_free(&str);
|
1999-04-22 10:48:28 +08:00
|
|
|
return ret;
|
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
1999-12-18 19:38:04 +08:00
|
|
|
#define PHP_PG_FIELD_NAME 1
|
|
|
|
#define PHP_PG_FIELD_SIZE 2
|
|
|
|
#define PHP_PG_FIELD_TYPE 3
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ php_pgsql_get_field_info
|
|
|
|
*/
|
2002-02-06 15:16:10 +08:00
|
|
|
static void php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-05-25 15:51:40 +08:00
|
|
|
zval **result, **field;
|
1999-04-22 10:48:28 +08:00
|
|
|
PGresult *pgsql_result;
|
|
|
|
pgsql_result_handle *pg_result;
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &result, &field)==FAILURE) {
|
1999-04-22 10:48:28 +08:00
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
}
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, result, -1, "PostgreSQL result", le_result);
|
|
|
|
|
1999-04-22 10:48:28 +08:00
|
|
|
pgsql_result = pg_result->result;
|
2000-05-25 15:51:40 +08:00
|
|
|
convert_to_long_ex(field);
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
if (Z_LVAL_PP(field) < 0 || Z_LVAL_PP(field) >= PQnfields(pgsql_result)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad field offset specified");
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (entry_type) {
|
1999-12-18 19:38:04 +08:00
|
|
|
case PHP_PG_FIELD_NAME:
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_STRVAL_P(return_value) = PQfname(pgsql_result, Z_LVAL_PP(field));
|
|
|
|
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
|
|
|
Z_STRVAL_P(return_value) = estrndup(Z_STRVAL_P(return_value),Z_STRLEN_P(return_value));
|
|
|
|
Z_TYPE_P(return_value) = IS_STRING;
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
1999-12-18 19:38:04 +08:00
|
|
|
case PHP_PG_FIELD_SIZE:
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_LVAL_P(return_value) = PQfsize(pgsql_result, Z_LVAL_PP(field));
|
|
|
|
Z_TYPE_P(return_value) = IS_LONG;
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
1999-12-18 19:38:04 +08:00
|
|
|
case PHP_PG_FIELD_TYPE:
|
2002-02-06 15:16:10 +08:00
|
|
|
Z_STRVAL_P(return_value) = get_field_name(pg_result->conn, PQftype(pgsql_result, Z_LVAL_PP(field)), &EG(regular_list) TSRMLS_CC);
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
|
|
|
Z_TYPE_P(return_value) = IS_STRING;
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto string pg_field_name(resource result, int field_number)
|
1999-04-22 10:48:28 +08:00
|
|
|
Returns the name of the field */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_field_name)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-12-18 19:38:04 +08:00
|
|
|
php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_FIELD_NAME);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto int pg_field_size(resource result, int field_number)
|
1999-04-22 10:48:28 +08:00
|
|
|
Returns the internal size of the field */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_field_size)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-12-18 19:38:04 +08:00
|
|
|
php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_FIELD_SIZE);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto string pg_field_type(resource result, int field_number)
|
1999-04-22 10:48:28 +08:00
|
|
|
Returns the type name for the given field */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_field_type)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-12-18 19:38:04 +08:00
|
|
|
php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_FIELD_TYPE);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto int pg_field_num(resource result, string field_name)
|
1999-04-22 10:48:28 +08:00
|
|
|
Returns the field number of the named field */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_field_num)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-05-25 15:51:40 +08:00
|
|
|
zval **result, **field;
|
1999-04-22 10:48:28 +08:00
|
|
|
PGresult *pgsql_result;
|
|
|
|
pgsql_result_handle *pg_result;
|
1999-11-20 08:30:08 +08:00
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &result, &field)==FAILURE) {
|
1999-04-22 10:48:28 +08:00
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
}
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, result, -1, "PostgreSQL result", le_result);
|
|
|
|
|
1999-04-22 10:48:28 +08:00
|
|
|
pgsql_result = pg_result->result;
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
convert_to_string_ex(field);
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_LVAL_P(return_value) = PQfnumber(pgsql_result, Z_STRVAL_PP(field));
|
|
|
|
Z_TYPE_P(return_value) = IS_LONG;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 19:53:38 +08:00
|
|
|
/* {{{ proto mixed pg_fetch_result(resource result, [int row_number,] mixed field_name)
|
1999-04-22 10:48:28 +08:00
|
|
|
Returns values from a result identifier */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_fetch_result)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-05-25 15:51:40 +08:00
|
|
|
zval **result, **row, **field=NULL;
|
1999-04-22 10:48:28 +08:00
|
|
|
PGresult *pgsql_result;
|
|
|
|
pgsql_result_handle *pg_result;
|
2001-06-20 02:10:08 +08:00
|
|
|
int field_offset, pgsql_row;
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-06-20 02:10:08 +08:00
|
|
|
if ((ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &result, &row, &field)==FAILURE) &&
|
|
|
|
(ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &result, &field)==FAILURE)) {
|
1999-04-22 10:48:28 +08:00
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
}
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, result, -1, "PostgreSQL result", le_result);
|
|
|
|
|
1999-04-22 10:48:28 +08:00
|
|
|
pgsql_result = pg_result->result;
|
2001-06-20 02:10:08 +08:00
|
|
|
if (ZEND_NUM_ARGS() == 2) {
|
|
|
|
if (pg_result->row < 0)
|
|
|
|
pg_result->row = 0;
|
|
|
|
pgsql_row = pg_result->row;
|
|
|
|
if (pgsql_row >= PQntuples(pgsql_result)) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
convert_to_long_ex(row);
|
|
|
|
pgsql_row = Z_LVAL_PP(row);
|
|
|
|
if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to jump to row %d on PostgreSQL result index %d", Z_LVAL_PP(row), Z_LVAL_PP(result));
|
2001-06-20 02:10:08 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2000-05-25 15:51:40 +08:00
|
|
|
switch(Z_TYPE_PP(field)) {
|
1999-04-22 10:48:28 +08:00
|
|
|
case IS_STRING:
|
2000-05-25 15:51:40 +08:00
|
|
|
field_offset = PQfnumber(pgsql_result, Z_STRVAL_PP(field));
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
|
|
|
default:
|
2000-05-25 15:51:40 +08:00
|
|
|
convert_to_long_ex(field);
|
|
|
|
field_offset = Z_LVAL_PP(field);
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (field_offset<0 || field_offset>=PQnfields(pgsql_result)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset specified");
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2001-06-20 02:10:08 +08:00
|
|
|
if (PQgetisnull(pgsql_result, pgsql_row, field_offset)) {
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_TYPE_P(return_value) = IS_NULL;
|
2000-08-16 09:03:20 +08:00
|
|
|
} else {
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_STRVAL_P(return_value) = PQgetvalue(pgsql_result, pgsql_row, field_offset);
|
|
|
|
Z_STRLEN_P(return_value) = (Z_STRVAL_P(return_value) ? strlen(Z_STRVAL_P(return_value)) : 0);
|
|
|
|
Z_STRVAL_P(return_value) = safe_estrndup(Z_STRVAL_P(return_value),Z_STRLEN_P(return_value));
|
|
|
|
Z_TYPE_P(return_value) = IS_STRING;
|
2000-08-16 09:03:20 +08:00
|
|
|
}
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-03-03 03:53:11 +08:00
|
|
|
/* {{{ void php_pgsql_fetch_hash */
|
1999-12-18 19:38:04 +08:00
|
|
|
static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-05-25 15:51:40 +08:00
|
|
|
zval **result, **row, **arg3;
|
1999-04-22 10:48:28 +08:00
|
|
|
PGresult *pgsql_result;
|
|
|
|
pgsql_result_handle *pg_result;
|
2001-06-20 02:10:08 +08:00
|
|
|
int i, num_fields, pgsql_row;
|
2000-05-25 15:51:40 +08:00
|
|
|
char *element, *field_name;
|
1999-04-22 10:48:28 +08:00
|
|
|
uint element_len;
|
1999-07-17 01:19:11 +08:00
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
switch (ZEND_NUM_ARGS()) {
|
2002-07-15 18:04:01 +08:00
|
|
|
case 1: /* pg_fetch_*(result) */
|
2002-03-03 03:53:11 +08:00
|
|
|
if (zend_get_parameters_ex(1, &result) == FAILURE) {
|
2001-06-20 02:10:08 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
break;
|
2002-07-15 18:04:01 +08:00
|
|
|
case 2: /* pg_fetch_*(result, row) */
|
2002-03-03 03:53:11 +08:00
|
|
|
if (zend_get_parameters_ex(2, &result, &row) == FAILURE) {
|
1999-07-17 01:19:11 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
break;
|
2002-07-15 18:04:01 +08:00
|
|
|
case 3: /* pg_fetch_*(result, row, result_type) */
|
2002-03-03 03:53:11 +08:00
|
|
|
if (zend_get_parameters_ex(3, &result, &row, &arg3) == FAILURE) {
|
1999-07-17 01:19:11 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2000-05-25 15:51:40 +08:00
|
|
|
convert_to_long_ex(arg3);
|
|
|
|
result_type = Z_LVAL_PP(arg3);
|
1999-07-17 01:19:11 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
break;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
|
2002-07-15 18:04:01 +08:00
|
|
|
if (!(result_type & PGSQL_BOTH)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid result type");
|
2002-07-15 18:04:01 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, result, -1, "PostgreSQL result", le_result);
|
|
|
|
|
1999-04-22 10:48:28 +08:00
|
|
|
pgsql_result = pg_result->result;
|
2001-06-20 02:10:08 +08:00
|
|
|
|
|
|
|
if (ZEND_NUM_ARGS() == 1) {
|
|
|
|
pg_result->row++;
|
|
|
|
pgsql_row = pg_result->row;
|
|
|
|
if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
2002-03-03 03:53:11 +08:00
|
|
|
if (Z_TYPE_PP(row) != IS_NULL) {
|
|
|
|
convert_to_long_ex(row);
|
|
|
|
pgsql_row = Z_LVAL_PP(row);
|
|
|
|
pg_result->row = pgsql_row;
|
|
|
|
if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to jump to row %d on PostgreSQL result index %d", Z_LVAL_PP(row), Z_LVAL_PP(result));
|
2002-03-03 03:53:11 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
2002-07-15 18:04:01 +08:00
|
|
|
/* If 2nd param is NULL, use internal row counter to access next row */
|
2002-03-03 03:53:11 +08:00
|
|
|
pg_result->row++;
|
|
|
|
pgsql_row = pg_result->row;
|
|
|
|
if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2001-06-20 02:10:08 +08:00
|
|
|
}
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
array_init(return_value);
|
2002-03-03 03:53:11 +08:00
|
|
|
for (i = 0, num_fields = PQnfields(pgsql_result); i < num_fields; i++) {
|
2001-06-20 02:10:08 +08:00
|
|
|
if (PQgetisnull(pgsql_result, pgsql_row, i)) {
|
2000-08-16 09:03:20 +08:00
|
|
|
if (result_type & PGSQL_NUM) {
|
2001-02-01 05:53:30 +08:00
|
|
|
add_index_null(return_value, i);
|
2000-09-09 17:40:16 +08:00
|
|
|
}
|
|
|
|
if (result_type & PGSQL_ASSOC) {
|
2000-08-16 09:03:20 +08:00
|
|
|
field_name = PQfname(pgsql_result, i);
|
2001-02-01 05:53:30 +08:00
|
|
|
add_assoc_null(return_value, field_name);
|
1999-07-17 01:19:11 +08:00
|
|
|
}
|
2000-08-16 09:03:20 +08:00
|
|
|
} else {
|
2001-06-20 02:10:08 +08:00
|
|
|
element = PQgetvalue(pgsql_result, pgsql_row, i);
|
2000-08-16 09:03:20 +08:00
|
|
|
element_len = (element ? strlen(element) : 0);
|
|
|
|
if (element) {
|
|
|
|
char *data;
|
|
|
|
int data_len;
|
|
|
|
int should_copy=0;
|
|
|
|
|
|
|
|
if (PG(magic_quotes_runtime)) {
|
2001-08-06 11:50:52 +08:00
|
|
|
data = php_addslashes(element, element_len, &data_len, 0 TSRMLS_CC);
|
2000-08-16 09:03:20 +08:00
|
|
|
} else {
|
|
|
|
data = safe_estrndup(element, element_len);
|
|
|
|
data_len = element_len;
|
|
|
|
}
|
1999-07-17 01:19:11 +08:00
|
|
|
|
2000-08-16 09:03:20 +08:00
|
|
|
if (result_type & PGSQL_NUM) {
|
|
|
|
add_index_stringl(return_value, i, data, data_len, should_copy);
|
|
|
|
should_copy=1;
|
|
|
|
}
|
1999-07-17 01:19:11 +08:00
|
|
|
|
2000-08-16 09:03:20 +08:00
|
|
|
if (result_type & PGSQL_ASSOC) {
|
|
|
|
field_name = PQfname(pgsql_result, i);
|
|
|
|
add_assoc_stringl(return_value, field_name, data, data_len, should_copy);
|
|
|
|
}
|
1999-07-17 01:19:11 +08:00
|
|
|
}
|
2000-08-16 09:03:20 +08:00
|
|
|
}
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
1999-07-17 01:19:11 +08:00
|
|
|
|
2002-07-15 18:04:01 +08:00
|
|
|
/* {{{ proto array pg_fetch_row(resource result [, int row [, int result_type]])
|
1999-07-17 01:26:16 +08:00
|
|
|
Get a row as an enumerated array */
|
1999-12-20 06:44:55 +08:00
|
|
|
PHP_FUNCTION(pg_fetch_row)
|
1999-07-17 01:26:16 +08:00
|
|
|
{
|
1999-12-18 19:38:04 +08:00
|
|
|
php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_NUM);
|
1999-07-17 01:26:16 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-03-03 03:53:11 +08:00
|
|
|
/* {{{ proto array pg_fetch_array(resource result [, int row [, int result_type]])
|
1999-04-22 10:48:28 +08:00
|
|
|
Fetch a row as an array */
|
1999-12-20 06:44:55 +08:00
|
|
|
PHP_FUNCTION(pg_fetch_array)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2002-07-15 18:04:01 +08:00
|
|
|
php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_BOTH);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-04-25 15:09:45 +08:00
|
|
|
/* {{{ proto object pg_fetch_object(resource result [, int row[, int result_type]])
|
1999-04-22 10:48:28 +08:00
|
|
|
Fetch a row as an object */
|
1999-12-20 06:44:55 +08:00
|
|
|
PHP_FUNCTION(pg_fetch_object)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2002-04-25 06:57:21 +08:00
|
|
|
php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_ASSOC);
|
2001-09-26 05:58:48 +08:00
|
|
|
if (Z_TYPE_P(return_value)==IS_ARRAY) {
|
2002-03-13 04:18:01 +08:00
|
|
|
object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value));
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-07-21 15:25:10 +08:00
|
|
|
/* {{{ proto array pg_fetch_all(resource result)
|
|
|
|
Fetch all rows into array */
|
|
|
|
PHP_FUNCTION(pg_fetch_all)
|
|
|
|
{
|
|
|
|
zval *result;
|
|
|
|
PGresult *pgsql_result;
|
|
|
|
pgsql_result_handle *pg_result;
|
|
|
|
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r",
|
|
|
|
&result) == FAILURE) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
|
|
|
|
|
|
|
|
pgsql_result = pg_result->result;
|
|
|
|
array_init(return_value);
|
|
|
|
if (php_pgsql_result2array(pgsql_result, return_value TSRMLS_CC) == FAILURE) {
|
|
|
|
zval_dtor(return_value);
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
1999-12-18 19:38:04 +08:00
|
|
|
#define PHP_PG_DATA_LENGTH 1
|
|
|
|
#define PHP_PG_DATA_ISNULL 2
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-06-05 21:12:10 +08:00
|
|
|
/* {{{ php_pgsql_data_info
|
|
|
|
*/
|
2002-02-06 15:16:10 +08:00
|
|
|
static void php_pgsql_data_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-05-25 15:51:40 +08:00
|
|
|
zval **result, **row, **field;
|
1999-04-22 10:48:28 +08:00
|
|
|
PGresult *pgsql_result;
|
|
|
|
pgsql_result_handle *pg_result;
|
2001-06-20 02:10:08 +08:00
|
|
|
int field_offset, pgsql_row;
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-06-20 02:10:08 +08:00
|
|
|
if ((ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &result, &row, &field)==FAILURE) &&
|
|
|
|
(ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &result, &field)==FAILURE)) {
|
1999-04-22 10:48:28 +08:00
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
}
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, result, -1, "PostgreSQL result", le_result);
|
|
|
|
|
1999-04-22 10:48:28 +08:00
|
|
|
pgsql_result = pg_result->result;
|
2001-06-20 02:10:08 +08:00
|
|
|
if (ZEND_NUM_ARGS() == 2) {
|
|
|
|
if (pg_result->row < 0)
|
|
|
|
pg_result->row = 0;
|
|
|
|
pgsql_row = pg_result->row;
|
|
|
|
if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
convert_to_long_ex(row);
|
|
|
|
pgsql_row = Z_LVAL_PP(row);
|
|
|
|
if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to jump to row %d on PostgreSQL result index %d", Z_LVAL_PP(row), Z_LVAL_PP(result));
|
2001-06-20 02:10:08 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2001-06-20 02:10:08 +08:00
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
switch(Z_TYPE_PP(field)) {
|
1999-04-22 10:48:28 +08:00
|
|
|
case IS_STRING:
|
2000-05-25 15:51:40 +08:00
|
|
|
convert_to_string_ex(field);
|
|
|
|
field_offset = PQfnumber(pgsql_result, Z_STRVAL_PP(field));
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
|
|
|
default:
|
2000-05-25 15:51:40 +08:00
|
|
|
convert_to_long_ex(field);
|
|
|
|
field_offset = Z_LVAL_PP(field);
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
|
|
|
}
|
2000-05-25 15:51:40 +08:00
|
|
|
if (field_offset < 0 || field_offset >= PQnfields(pgsql_result)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset specified");
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (entry_type) {
|
1999-12-18 19:38:04 +08:00
|
|
|
case PHP_PG_DATA_LENGTH:
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_LVAL_P(return_value) = PQgetlength(pgsql_result, pgsql_row, field_offset);
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
1999-12-18 19:38:04 +08:00
|
|
|
case PHP_PG_DATA_ISNULL:
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_LVAL_P(return_value) = PQgetisnull(pgsql_result, pgsql_row, field_offset);
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
|
|
|
}
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_TYPE_P(return_value) = IS_LONG;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto int pg_field_prtlen(resource result, [int row,] mixed field_name_or_number)
|
1999-04-22 10:48:28 +08:00
|
|
|
Returns the printed length */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_field_prtlen)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-12-18 19:38:04 +08:00
|
|
|
php_pgsql_data_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_DATA_LENGTH);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto int pg_field_is_null(resource result, [int row,] mixed field_name_or_number)
|
1999-04-22 10:48:28 +08:00
|
|
|
Test if a field is NULL */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_field_is_null)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
1999-12-18 19:38:04 +08:00
|
|
|
php_pgsql_data_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_DATA_ISNULL);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto bool pg_free_result(resource result)
|
1999-04-22 10:48:28 +08:00
|
|
|
Free result memory */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_free_result)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-05-25 15:51:40 +08:00
|
|
|
zval **result;
|
1999-04-22 10:48:28 +08:00
|
|
|
pgsql_result_handle *pg_result;
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &result)==FAILURE) {
|
1999-04-22 10:48:28 +08:00
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
}
|
2000-05-25 15:51:40 +08:00
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, result, -1, "PostgreSQL result", le_result);
|
|
|
|
if (Z_LVAL_PP(result) == 0) {
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2000-05-25 15:51:40 +08:00
|
|
|
zend_list_delete(Z_LVAL_PP(result));
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-07-11 23:45:35 +08:00
|
|
|
/* {{{ proto string pg_last_oid(resource result)
|
1999-04-22 10:48:28 +08:00
|
|
|
Returns the last object identifier */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_last_oid)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-05-25 15:51:40 +08:00
|
|
|
zval **result;
|
1999-04-22 10:48:28 +08:00
|
|
|
PGresult *pgsql_result;
|
|
|
|
pgsql_result_handle *pg_result;
|
2002-04-20 11:37:01 +08:00
|
|
|
Oid oid;
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &result)==FAILURE) {
|
1999-04-22 10:48:28 +08:00
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
}
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, result, -1, "PostgreSQL result", le_result);
|
1999-04-22 10:48:28 +08:00
|
|
|
pgsql_result = pg_result->result;
|
2002-03-29 19:24:54 +08:00
|
|
|
#ifdef HAVE_PQOIDVALUE
|
2002-04-20 11:03:42 +08:00
|
|
|
oid = PQoidValue(pgsql_result);
|
|
|
|
if (oid == InvalidOid) {
|
2001-12-17 08:24:59 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2002-04-21 18:22:31 +08:00
|
|
|
PGSQL_RETURN_OID(oid);
|
2001-12-17 08:24:59 +08:00
|
|
|
#else
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_STRVAL_P(return_value) = (char *) PQoidStatus(pgsql_result);
|
|
|
|
if (Z_STRVAL_P(return_value)) {
|
2002-04-21 18:22:31 +08:00
|
|
|
RETURN_STRING(Z_STRVAL_P(return_value), 1);
|
2000-05-23 14:03:34 +08:00
|
|
|
}
|
2002-04-20 11:37:01 +08:00
|
|
|
RETURN_STRING(empty_string, 0);
|
2000-05-23 14:03:34 +08:00
|
|
|
#endif
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2000-06-01 04:40:28 +08:00
|
|
|
/* {{{ proto bool pg_trace(string filename [, string mode [, resource connection]])
|
2000-06-24 01:09:54 +08:00
|
|
|
Enable tracing a PostgreSQL connection */
|
2000-06-01 04:40:28 +08:00
|
|
|
PHP_FUNCTION(pg_trace)
|
|
|
|
{
|
2000-07-29 14:07:26 +08:00
|
|
|
zval **z_filename, **z_mode, **z_pgsql_link = NULL;
|
2000-06-01 04:40:28 +08:00
|
|
|
int id = -1;
|
|
|
|
PGconn *pgsql;
|
|
|
|
char *mode = "w";
|
2002-04-07 13:21:43 +08:00
|
|
|
FILE *fp = NULL;
|
2002-03-16 09:28:57 +08:00
|
|
|
php_stream *stream;
|
2000-06-01 04:40:28 +08:00
|
|
|
id = PGG(default_link);
|
|
|
|
|
|
|
|
switch (ZEND_NUM_ARGS()) {
|
|
|
|
case 1:
|
|
|
|
if (zend_get_parameters_ex(1, &z_filename)==FAILURE) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2000-07-29 14:07:26 +08:00
|
|
|
CHECK_DEFAULT_LINK(id);
|
2000-06-01 04:40:28 +08:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if (zend_get_parameters_ex(2, &z_filename, &z_mode)==FAILURE) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2000-07-29 14:07:26 +08:00
|
|
|
CHECK_DEFAULT_LINK(id);
|
2000-06-01 04:40:28 +08:00
|
|
|
convert_to_string_ex(z_mode);
|
|
|
|
mode = Z_STRVAL_PP(z_mode);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
if (zend_get_parameters_ex(3, &z_filename, &z_mode, &z_pgsql_link)==FAILURE) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
convert_to_string_ex(z_mode);
|
|
|
|
mode = Z_STRVAL_PP(z_mode);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ZEND_WRONG_PARAM_COUNT();
|
|
|
|
break;
|
|
|
|
}
|
2002-08-24 04:57:30 +08:00
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, z_pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
2000-06-01 04:40:28 +08:00
|
|
|
convert_to_string_ex(z_filename);
|
|
|
|
|
2002-03-18 06:50:59 +08:00
|
|
|
stream = php_stream_open_wrapper(Z_STRVAL_PP(z_filename), mode, ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
|
2000-06-01 04:40:28 +08:00
|
|
|
|
2002-03-16 05:03:08 +08:00
|
|
|
if (!stream) {
|
2000-06-01 04:40:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2002-03-16 05:03:08 +08:00
|
|
|
|
2002-03-22 06:35:02 +08:00
|
|
|
if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void**)fp, REPORT_ERRORS)) {
|
2002-03-16 05:03:08 +08:00
|
|
|
php_stream_close(stream);
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2002-03-20 22:21:30 +08:00
|
|
|
php_stream_auto_cleanup(stream);
|
2000-06-01 04:40:28 +08:00
|
|
|
PQtrace(pgsql, fp);
|
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
2000-06-01 04:40:28 +08:00
|
|
|
|
2001-12-10 14:14:03 +08:00
|
|
|
/* {{{ proto bool pg_untrace([resource connection])
|
2000-06-01 04:40:28 +08:00
|
|
|
Disable tracing of a PostgreSQL connection */
|
|
|
|
PHP_FUNCTION(pg_untrace)
|
|
|
|
{
|
2000-07-29 14:07:26 +08:00
|
|
|
zval **pgsql_link = NULL;
|
2000-06-01 04:40:28 +08:00
|
|
|
int id = -1;
|
|
|
|
PGconn *pgsql;
|
|
|
|
|
|
|
|
switch (ZEND_NUM_ARGS()) {
|
|
|
|
case 0:
|
|
|
|
id = PGG(default_link);
|
2000-07-29 14:07:26 +08:00
|
|
|
CHECK_DEFAULT_LINK(id);
|
2000-06-01 04:40:28 +08:00
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if (zend_get_parameters_ex(1, &pgsql_link)==FAILURE) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ZEND_WRONG_PARAM_COUNT();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
PQuntrace(pgsql);
|
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
2001-06-05 21:12:10 +08:00
|
|
|
/* }}} */
|
2000-06-01 04:40:28 +08:00
|
|
|
|
2002-07-11 23:45:35 +08:00
|
|
|
/* {{{ proto int pg_lo_create([resource connection])
|
1999-04-22 10:48:28 +08:00
|
|
|
Create a large object */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_lo_create)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-07-29 14:07:26 +08:00
|
|
|
zval **pgsql_link = NULL;
|
1999-04-22 10:48:28 +08:00
|
|
|
PGconn *pgsql;
|
|
|
|
Oid pgsql_oid;
|
2000-05-25 15:51:40 +08:00
|
|
|
int id = -1;
|
1999-11-20 08:30:08 +08:00
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
switch(ZEND_NUM_ARGS()) {
|
1999-04-22 10:48:28 +08:00
|
|
|
case 0:
|
1999-11-20 08:30:08 +08:00
|
|
|
id = PGG(default_link);
|
2000-07-29 14:07:26 +08:00
|
|
|
CHECK_DEFAULT_LINK(id);
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
|
|
|
case 1:
|
2000-05-25 15:51:40 +08:00
|
|
|
if (zend_get_parameters_ex(1, &pgsql_link)==FAILURE) {
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2002-09-05 06:25:13 +08:00
|
|
|
/* NOTE: Archive modes not supported until I get some more data. Don't think anybody's
|
1999-04-22 10:48:28 +08:00
|
|
|
using it anyway. I believe it's also somehow related to the 'time travel' feature of
|
|
|
|
PostgreSQL, that's on the list of features to be removed... Create modes not supported.
|
|
|
|
What's the use of an object that can be only written to, but not read from, and vice
|
|
|
|
versa? Beats me... And the access type (r/w) must be specified again when opening
|
|
|
|
the object, probably (?) overrides this. (Jouni)
|
2002-03-11 15:23:07 +08:00
|
|
|
*/
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2002-04-20 11:37:01 +08:00
|
|
|
if ((pgsql_oid = lo_creat(pgsql, INV_READ|INV_WRITE)) == InvalidOid) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create PostgreSQL large object");
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2002-04-21 18:22:31 +08:00
|
|
|
PGSQL_RETURN_OID(pgsql_oid);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-07-11 23:45:35 +08:00
|
|
|
/* {{{ proto bool pg_lo_unlink([resource connection,] string large_object_oid)
|
1999-04-22 10:48:28 +08:00
|
|
|
Delete a large object */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_lo_unlink)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2002-04-20 22:06:47 +08:00
|
|
|
zval *pgsql_link = NULL;
|
|
|
|
long oid_long;
|
|
|
|
char *oid_string, *end_ptr;
|
|
|
|
size_t oid_strlen;
|
1999-04-22 10:48:28 +08:00
|
|
|
PGconn *pgsql;
|
2002-04-20 22:06:47 +08:00
|
|
|
Oid oid;
|
2000-05-25 15:51:40 +08:00
|
|
|
int id = -1;
|
2002-04-20 22:06:47 +08:00
|
|
|
int argc = ZEND_NUM_ARGS();
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2002-04-20 22:06:47 +08:00
|
|
|
/* accept string type since Oid type is unsigned int */
|
|
|
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
|
|
|
|
"rs", &pgsql_link, &oid_string, &oid_strlen) == SUCCESS) {
|
|
|
|
oid = (Oid)strtoul(oid_string, &end_ptr, 10);
|
|
|
|
if ((oid_string+oid_strlen) != end_ptr) {
|
|
|
|
/* wrong integer format */
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
|
2002-04-20 22:06:47 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
|
|
|
|
"rl", &pgsql_link, &oid_long) == SUCCESS) {
|
|
|
|
if (oid_long <= InvalidOid) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID is specified");
|
2002-04-20 22:06:47 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
oid = (Oid)oid_long;
|
|
|
|
}
|
|
|
|
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
|
|
|
|
"s", &oid_string, &oid_strlen) == SUCCESS) {
|
|
|
|
oid = (Oid)strtoul(oid_string, &end_ptr, 10);
|
|
|
|
if ((oid_string+oid_strlen) != end_ptr) {
|
|
|
|
/* wrong integer format */
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
|
2002-04-20 22:06:47 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
id = PGG(default_link);
|
|
|
|
CHECK_DEFAULT_LINK(id);
|
|
|
|
}
|
|
|
|
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
|
|
|
|
"l", &oid_long) == SUCCESS) {
|
|
|
|
if (oid_long <= InvalidOid) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID is specified");
|
2002-04-20 22:06:47 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
oid = (Oid)oid_long;
|
|
|
|
id = PGG(default_link);
|
|
|
|
CHECK_DEFAULT_LINK(id);
|
|
|
|
}
|
|
|
|
else {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Requires 1 or 2 arguments");
|
2002-04-20 22:06:47 +08:00
|
|
|
RETURN_FALSE;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
|
2002-04-20 22:06:47 +08:00
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
|
|
|
if (lo_unlink(pgsql, oid) == -1) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to delete PostgreSQL large object %u", oid);
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto resource pg_lo_open([resource connection,] int large_object_oid, string mode)
|
1999-04-22 10:48:28 +08:00
|
|
|
Open a large object and return fd */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_lo_open)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2002-04-20 22:06:47 +08:00
|
|
|
zval *pgsql_link = NULL;
|
|
|
|
long oid_long;
|
|
|
|
char *oid_string, *end_ptr, *mode_string;
|
|
|
|
size_t oid_strlen, mode_strlen;
|
1999-04-22 10:48:28 +08:00
|
|
|
PGconn *pgsql;
|
2002-04-20 22:06:47 +08:00
|
|
|
Oid oid;
|
2000-05-25 15:51:40 +08:00
|
|
|
int id = -1, pgsql_mode=0, pgsql_lofd;
|
1999-04-22 10:48:28 +08:00
|
|
|
int create=0;
|
|
|
|
pgLofp *pgsql_lofp;
|
2002-04-20 22:06:47 +08:00
|
|
|
int argc = ZEND_NUM_ARGS();
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2002-04-20 22:06:47 +08:00
|
|
|
/* accept string type since Oid is unsigned int */
|
|
|
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
|
|
|
|
"rss", &pgsql_link, &oid_string, &oid_strlen, &mode_string, &mode_strlen) == SUCCESS) {
|
|
|
|
oid = (Oid)strtoul(oid_string, &end_ptr, 10);
|
|
|
|
if ((oid_string+oid_strlen) != end_ptr) {
|
|
|
|
/* wrong integer format */
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
|
2002-04-20 22:06:47 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2002-04-20 22:06:47 +08:00
|
|
|
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
|
|
|
|
"rls", &pgsql_link, &oid_long, &mode_string, &mode_strlen) == SUCCESS) {
|
|
|
|
if (oid_long <= InvalidOid) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID is specified");
|
2002-04-20 22:06:47 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
oid = (Oid)oid_long;
|
|
|
|
}
|
|
|
|
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
|
|
|
|
"ss", &oid_string, &oid_strlen, &mode_string, &mode_strlen) == SUCCESS) {
|
|
|
|
oid = (Oid)strtoul(oid_string, &end_ptr, 10);
|
|
|
|
if ((oid_string+oid_strlen) != end_ptr) {
|
|
|
|
/* wrong integer format */
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
|
2002-04-20 22:06:47 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
id = PGG(default_link);
|
|
|
|
CHECK_DEFAULT_LINK(id);
|
|
|
|
}
|
|
|
|
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
|
|
|
|
"ls", &oid_long, &mode_string, &mode_strlen) == SUCCESS) {
|
|
|
|
if (oid_long <= InvalidOid) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID is specified");
|
2002-04-20 22:06:47 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
oid = (Oid)oid_long;
|
|
|
|
id = PGG(default_link);
|
|
|
|
CHECK_DEFAULT_LINK(id);
|
|
|
|
}
|
|
|
|
else {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Requires 1 or 2 arguments");
|
2002-04-20 22:06:47 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
1999-04-22 10:48:28 +08:00
|
|
|
|
|
|
|
/* r/w/+ is little bit more PHP-like than INV_READ/INV_WRITE and a lot of
|
|
|
|
faster to type. Unfortunately, doesn't behave the same way as fopen()...
|
|
|
|
(Jouni)
|
2002-03-11 15:23:07 +08:00
|
|
|
*/
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
if (strchr(mode_string, 'r') == mode_string) {
|
1999-04-22 10:48:28 +08:00
|
|
|
pgsql_mode |= INV_READ;
|
2000-05-25 15:51:40 +08:00
|
|
|
if (strchr(mode_string, '+') == mode_string+1) {
|
1999-04-22 10:48:28 +08:00
|
|
|
pgsql_mode |= INV_WRITE;
|
|
|
|
}
|
|
|
|
}
|
2000-05-25 15:51:40 +08:00
|
|
|
if (strchr(mode_string, 'w') == mode_string) {
|
1999-04-22 10:48:28 +08:00
|
|
|
pgsql_mode |= INV_WRITE;
|
|
|
|
create = 1;
|
2000-05-25 15:51:40 +08:00
|
|
|
if (strchr(mode_string, '+') == mode_string+1) {
|
1999-04-22 10:48:28 +08:00
|
|
|
pgsql_mode |= INV_READ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pgsql_lofp = (pgLofp *) emalloc(sizeof(pgLofp));
|
|
|
|
|
2002-04-20 22:06:47 +08:00
|
|
|
if ((pgsql_lofd = lo_open(pgsql, oid, pgsql_mode)) == -1) {
|
1999-04-22 10:48:28 +08:00
|
|
|
if (create) {
|
2002-04-20 22:06:47 +08:00
|
|
|
if ((oid = lo_creat(pgsql, INV_READ|INV_WRITE)) == 0) {
|
1999-04-22 10:48:28 +08:00
|
|
|
efree(pgsql_lofp);
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create PostgreSQL large object");
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
} else {
|
2002-04-20 22:06:47 +08:00
|
|
|
if ((pgsql_lofd = lo_open(pgsql, oid, pgsql_mode)) == -1) {
|
|
|
|
if (lo_unlink(pgsql, oid) == -1) {
|
1999-04-22 10:48:28 +08:00
|
|
|
efree(pgsql_lofp);
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Something's really messed up!!! Your database is badly corrupted in a way NOT related to PHP");
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
efree(pgsql_lofp);
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open PostgreSQL large object");
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
} else {
|
|
|
|
pgsql_lofp->conn = pgsql;
|
|
|
|
pgsql_lofp->lofd = pgsql_lofd;
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_LVAL_P(return_value) = zend_list_insert(pgsql_lofp, le_lofp);
|
|
|
|
Z_TYPE_P(return_value) = IS_LONG;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
efree(pgsql_lofp);
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open PostgreSQL large object");
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
pgsql_lofp->conn = pgsql;
|
|
|
|
pgsql_lofp->lofd = pgsql_lofd;
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_REGISTER_RESOURCE(return_value, pgsql_lofp, le_lofp);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto bool pg_lo_close(resource large_object)
|
1999-04-22 10:48:28 +08:00
|
|
|
Close a large object */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_lo_close)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-05-25 15:51:40 +08:00
|
|
|
zval **pgsql_lofp;
|
1999-04-22 10:48:28 +08:00
|
|
|
pgLofp *pgsql;
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
switch(ZEND_NUM_ARGS()) {
|
1999-04-22 10:48:28 +08:00
|
|
|
case 1:
|
2000-05-25 15:51:40 +08:00
|
|
|
if (zend_get_parameters_ex(1, &pgsql_lofp)==FAILURE) {
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_FETCH_RESOURCE(pgsql, pgLofp *, pgsql_lofp, -1, "PostgreSQL large object", le_lofp);
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
if (lo_close((PGconn *)pgsql->conn, pgsql->lofd) < 0) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to close PostgreSQL large object descriptor %d", pgsql->lofd);
|
1999-04-22 10:48:28 +08:00
|
|
|
RETVAL_FALSE;
|
|
|
|
} else {
|
|
|
|
RETVAL_TRUE;
|
|
|
|
}
|
2000-05-25 15:51:40 +08:00
|
|
|
|
2002-04-20 11:37:01 +08:00
|
|
|
zend_list_delete(Z_RESVAL_PP(pgsql_lofp));
|
1999-04-22 10:48:28 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-05-20 09:02:29 +08:00
|
|
|
#define PGSQL_LO_READ_BUF_SIZE 8192
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto string pg_lo_read(resource large_object [, int len])
|
1999-04-22 10:48:28 +08:00
|
|
|
Read a large object */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_lo_read)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-05-25 15:51:40 +08:00
|
|
|
zval **pgsql_id, **len;
|
2002-05-20 09:02:29 +08:00
|
|
|
int buf_len = PGSQL_LO_READ_BUF_SIZE, nbytes;
|
1999-04-22 10:48:28 +08:00
|
|
|
char *buf;
|
|
|
|
pgLofp *pgsql;
|
|
|
|
|
2001-05-27 09:10:36 +08:00
|
|
|
if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 2 ||
|
|
|
|
zend_get_parameters_ex(ZEND_NUM_ARGS(), &pgsql_id, &len) == FAILURE) {
|
|
|
|
WRONG_PARAM_COUNT;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_FETCH_RESOURCE(pgsql, pgLofp *, pgsql_id, -1, "PostgreSQL large object", le_lofp);
|
|
|
|
|
2001-05-27 09:10:36 +08:00
|
|
|
if (ZEND_NUM_ARGS() > 1) {
|
|
|
|
convert_to_long_ex(len);
|
|
|
|
buf_len = Z_LVAL_PP(len);
|
|
|
|
}
|
|
|
|
|
1999-04-22 10:48:28 +08:00
|
|
|
buf = (char *) emalloc(sizeof(char)*(buf_len+1));
|
|
|
|
if ((nbytes = lo_read((PGconn *)pgsql->conn, pgsql->lofd, buf, buf_len))<0) {
|
|
|
|
efree(buf);
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2001-05-27 09:10:36 +08:00
|
|
|
|
2002-04-20 11:37:01 +08:00
|
|
|
buf[nbytes] = '\0';
|
2001-05-27 09:10:36 +08:00
|
|
|
RETURN_STRINGL(buf, nbytes, 0);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto int pg_lo_write(resource large_object, string buf [, int len])
|
1999-04-22 10:48:28 +08:00
|
|
|
Write a large object */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_lo_write)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2001-05-27 09:10:36 +08:00
|
|
|
zval **pgsql_id, **str, **z_len;
|
2000-05-25 15:51:40 +08:00
|
|
|
int nbytes;
|
2001-05-27 09:10:36 +08:00
|
|
|
int len;
|
1999-04-22 10:48:28 +08:00
|
|
|
pgLofp *pgsql;
|
2001-05-27 09:10:36 +08:00
|
|
|
int argc = ZEND_NUM_ARGS();
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2001-05-27 09:10:36 +08:00
|
|
|
if (argc < 2 || argc > 3 ||
|
|
|
|
zend_get_parameters_ex(argc, &pgsql_id, &str, &z_len) == FAILURE) {
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
}
|
|
|
|
|
|
|
|
convert_to_string_ex(str);
|
|
|
|
|
|
|
|
if (argc > 2) {
|
|
|
|
convert_to_long_ex(z_len);
|
2002-05-20 09:40:22 +08:00
|
|
|
if (Z_LVAL_PP(z_len) > Z_STRLEN_PP(str)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot write more than buffer size %d. Tried to wtite %d", Z_LVAL_PP(str), Z_LVAL_PP(z_len));
|
2002-05-20 09:40:22 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
if (Z_LVAL_PP(z_len) < 0) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Buffer size must be larger than 0. %d specified for buffer size", Z_LVAL_PP(str), Z_LVAL_PP(z_len));
|
2002-05-20 09:40:22 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2001-05-27 09:10:36 +08:00
|
|
|
len = Z_LVAL_PP(z_len);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
len = Z_STRLEN_PP(str);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_FETCH_RESOURCE(pgsql, pgLofp *, pgsql_id, -1, "PostgreSQL large object", le_lofp);
|
|
|
|
|
2001-05-27 09:10:36 +08:00
|
|
|
if ((nbytes = lo_write((PGconn *)pgsql->conn, pgsql->lofd, Z_STRVAL_PP(str), len)) == -1) {
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2001-05-27 09:10:36 +08:00
|
|
|
|
|
|
|
RETURN_LONG(nbytes);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto int pg_lo_read_all(resource large_object)
|
1999-04-22 10:48:28 +08:00
|
|
|
Read a large object and send straight to browser */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_lo_read_all)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-05-25 15:51:40 +08:00
|
|
|
zval **pgsql_id;
|
2002-05-20 09:40:22 +08:00
|
|
|
int tbytes;
|
1999-04-22 10:48:28 +08:00
|
|
|
volatile int nbytes;
|
2002-05-20 09:02:29 +08:00
|
|
|
char buf[PGSQL_LO_READ_BUF_SIZE];
|
1999-04-22 10:48:28 +08:00
|
|
|
pgLofp *pgsql;
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
switch(ZEND_NUM_ARGS()) {
|
1999-04-22 10:48:28 +08:00
|
|
|
case 1:
|
2000-06-27 21:26:04 +08:00
|
|
|
if (zend_get_parameters_ex(1, &pgsql_id)==FAILURE) {
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2000-05-25 15:51:40 +08:00
|
|
|
ZEND_FETCH_RESOURCE(pgsql, pgLofp *, pgsql_id, -1, "PostgreSQL large object", le_lofp);
|
1999-04-22 10:48:28 +08:00
|
|
|
|
|
|
|
tbytes = 0;
|
2002-05-20 09:02:29 +08:00
|
|
|
while ((nbytes = lo_read((PGconn *)pgsql->conn, pgsql->lofd, buf, PGSQL_LO_READ_BUF_SIZE))>0) {
|
|
|
|
php_body_write(buf, nbytes TSRMLS_CC);
|
|
|
|
tbytes += nbytes;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2001-12-17 08:24:59 +08:00
|
|
|
RETURN_LONG(tbytes);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
2000-06-05 04:24:07 +08:00
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto int pg_lo_import([resource connection, ] string filename)
|
2000-06-05 04:24:07 +08:00
|
|
|
Import large object direct from filesystem */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_lo_import)
|
2000-06-05 04:24:07 +08:00
|
|
|
{
|
2001-12-17 08:24:59 +08:00
|
|
|
zval *pgsql_link = NULL;
|
2002-04-21 17:46:29 +08:00
|
|
|
char *file_in;
|
2001-12-17 08:24:59 +08:00
|
|
|
int id = -1, name_len;
|
|
|
|
int argc = ZEND_NUM_ARGS();
|
2000-06-05 04:24:07 +08:00
|
|
|
PGconn *pgsql;
|
|
|
|
Oid oid;
|
2001-12-17 08:24:59 +08:00
|
|
|
|
|
|
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
|
|
|
|
"rs", &pgsql_link, &file_in, &name_len) == SUCCESS) {
|
|
|
|
;
|
|
|
|
}
|
|
|
|
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
|
2002-03-11 15:23:07 +08:00
|
|
|
"s", &file_in, &name_len) == SUCCESS) {
|
2001-12-17 08:24:59 +08:00
|
|
|
id = PGG(default_link);
|
|
|
|
CHECK_DEFAULT_LINK(id);
|
|
|
|
}
|
|
|
|
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
|
2002-05-20 09:02:29 +08:00
|
|
|
"sr", &file_in, &name_len, &pgsql_link ) == SUCCESS) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Old API is used.");
|
2001-12-17 08:24:59 +08:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
WRONG_PARAM_COUNT;
|
2000-06-05 04:24:07 +08:00
|
|
|
}
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
if (PG(safe_mode) &&(!php_checkuid(file_in, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
|
2000-06-05 04:24:07 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2002-07-17 12:58:58 +08:00
|
|
|
|
|
|
|
if (php_check_open_basedir(file_in TSRMLS_CC)) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2000-06-05 04:24:07 +08:00
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
2000-06-05 04:24:07 +08:00
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
oid = lo_import(pgsql, file_in);
|
2000-06-05 04:24:07 +08:00
|
|
|
|
2002-04-20 11:37:01 +08:00
|
|
|
if (oid == InvalidOid) {
|
2000-06-05 04:24:07 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2002-04-21 18:22:31 +08:00
|
|
|
PGSQL_RETURN_OID(oid);
|
2000-06-05 04:24:07 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto bool pg_lo_export([resource connection, ] int objoid, string filename)
|
2000-06-19 00:31:52 +08:00
|
|
|
Export large object direct to filesystem */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_lo_export)
|
2000-06-05 04:24:07 +08:00
|
|
|
{
|
2001-12-17 08:24:59 +08:00
|
|
|
zval *pgsql_link = NULL;
|
2002-04-20 22:06:47 +08:00
|
|
|
char *file_out, *oid_string, *end_ptr;
|
|
|
|
size_t oid_strlen;
|
|
|
|
int id = -1, name_len;
|
|
|
|
long oid_long;
|
2000-06-05 04:24:07 +08:00
|
|
|
Oid oid;
|
|
|
|
PGconn *pgsql;
|
2002-04-20 22:06:47 +08:00
|
|
|
int argc = ZEND_NUM_ARGS();
|
2002-04-20 12:17:17 +08:00
|
|
|
|
2002-04-20 22:06:47 +08:00
|
|
|
/* allow string to handle large OID value correctly */
|
2001-12-17 08:24:59 +08:00
|
|
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
|
2002-04-20 22:06:47 +08:00
|
|
|
"rls", &pgsql_link, &oid_long, &file_out, &name_len) == SUCCESS) {
|
|
|
|
if (oid_long <= InvalidOid) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID is specified");
|
2002-04-20 22:06:47 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
oid = (Oid)oid_long;
|
2001-12-17 08:24:59 +08:00
|
|
|
}
|
|
|
|
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
|
2002-04-20 22:06:47 +08:00
|
|
|
"rss", &pgsql_link, &oid_string, &oid_strlen, &file_out, &name_len) == SUCCESS) {
|
|
|
|
oid = (Oid)strtoul(oid_string, &end_ptr, 10);
|
|
|
|
if ((oid_string+oid_strlen) != end_ptr) {
|
|
|
|
/* wrong integer format */
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
|
2002-04-20 22:06:47 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
|
|
|
|
"ls", &oid_long, &file_out, &name_len) == SUCCESS) {
|
|
|
|
if (oid_long <= InvalidOid) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID is specified");
|
2002-04-20 22:06:47 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
oid = (Oid)oid_long;
|
|
|
|
id = PGG(default_link);
|
|
|
|
CHECK_DEFAULT_LINK(id);
|
|
|
|
}
|
|
|
|
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
|
|
|
|
"ss", &pgsql_link, &oid_string, &oid_strlen, &file_out, &name_len) == SUCCESS) {
|
|
|
|
oid = (Oid)strtoul(oid_string, &end_ptr, 10);
|
|
|
|
if ((oid_string+oid_strlen) != end_ptr) {
|
|
|
|
/* wrong integer format */
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
|
2002-04-20 22:06:47 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2001-12-17 08:24:59 +08:00
|
|
|
id = PGG(default_link);
|
|
|
|
CHECK_DEFAULT_LINK(id);
|
|
|
|
}
|
|
|
|
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
|
2002-04-20 22:06:47 +08:00
|
|
|
"ssr", &oid_string, &oid_strlen, &file_out, &name_len, &pgsql_link) == SUCCESS) {
|
|
|
|
oid = (Oid)strtoul(oid_string, &end_ptr, 10);
|
|
|
|
if ((oid_string+oid_strlen) != end_ptr) {
|
|
|
|
/* wrong integer format */
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
|
2002-04-20 22:06:47 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
|
|
|
|
"lsr", &oid_long, &file_out, &name_len, &pgsql_link) == SUCCESS) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, " %s(): Old API is used");
|
2002-04-20 22:06:47 +08:00
|
|
|
if (oid_long <= InvalidOid) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID is specified");
|
2002-04-20 22:06:47 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
oid = (Oid)oid_long;
|
2001-12-17 08:24:59 +08:00
|
|
|
}
|
|
|
|
else {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Requires 2 or 3 arguments");
|
2002-04-20 22:06:47 +08:00
|
|
|
RETURN_FALSE;
|
2000-06-05 04:24:07 +08:00
|
|
|
}
|
|
|
|
|
2002-07-17 15:50:32 +08:00
|
|
|
if (PG(safe_mode) &&(!php_checkuid(file_out, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
|
2002-07-17 13:01:58 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2002-07-17 15:50:32 +08:00
|
|
|
if (php_check_open_basedir(file_out TSRMLS_CC)) {
|
2002-07-17 13:01:58 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
2000-06-05 04:24:07 +08:00
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
if (lo_export(pgsql, oid, file_out)) {
|
2000-06-05 04:24:07 +08:00
|
|
|
RETURN_TRUE;
|
2002-04-20 22:06:47 +08:00
|
|
|
}
|
|
|
|
RETURN_FALSE;
|
2000-06-05 04:24:07 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 20:14:46 +08:00
|
|
|
/* {{{ proto bool pg_lo_seek(resource large_object, int offset [, int whence])
|
2001-12-17 08:24:59 +08:00
|
|
|
Seeks position of large object */
|
|
|
|
PHP_FUNCTION(pg_lo_seek)
|
|
|
|
{
|
|
|
|
zval *pgsql_id = NULL;
|
|
|
|
int offset = 0, whence = SEEK_CUR;
|
|
|
|
pgLofp *pgsql;
|
|
|
|
int argc = ZEND_NUM_ARGS();
|
2000-07-02 16:59:44 +08:00
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
if (zend_parse_parameters(argc TSRMLS_CC, "rl|l", &pgsql_id, &offset, &whence) == FAILURE) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid whence parameter");
|
2001-12-17 08:24:59 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_id, -1, "PostgreSQL large object", le_lofp);
|
|
|
|
|
|
|
|
if (lo_lseek((PGconn *)pgsql->conn, pgsql->lofd, offset, whence )) {
|
|
|
|
RETURN_TRUE;
|
|
|
|
} else {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto int pg_lo_tell(resource large_object)
|
|
|
|
Returns current position of large object */
|
|
|
|
PHP_FUNCTION(pg_lo_tell)
|
|
|
|
{
|
|
|
|
zval *pgsql_id = NULL;
|
|
|
|
int offset = 0;
|
|
|
|
pgLofp *pgsql;
|
|
|
|
int argc = ZEND_NUM_ARGS();
|
|
|
|
|
|
|
|
if (zend_parse_parameters(argc TSRMLS_CC, "r", &pgsql_id) == FAILURE) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_id, -1, "PostgreSQL large object", le_lofp);
|
|
|
|
|
|
|
|
offset = lo_tell((PGconn *)pgsql->conn, pgsql->lofd);
|
|
|
|
RETURN_LONG(offset);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-04-25 15:09:45 +08:00
|
|
|
#ifdef HAVE_PQCLIENTENCODING
|
2001-12-10 14:14:03 +08:00
|
|
|
/* {{{ proto int pg_set_client_encoding([resource connection,] string encoding)
|
2000-07-02 16:59:44 +08:00
|
|
|
Set client encoding */
|
2000-09-13 12:13:36 +08:00
|
|
|
PHP_FUNCTION(pg_set_client_encoding)
|
2000-07-02 16:59:44 +08:00
|
|
|
{
|
2000-07-29 14:07:26 +08:00
|
|
|
zval **encoding, **pgsql_link = NULL;
|
2000-07-02 16:59:44 +08:00
|
|
|
int id = -1;
|
|
|
|
PGconn *pgsql;
|
|
|
|
|
|
|
|
switch(ZEND_NUM_ARGS()) {
|
|
|
|
case 1:
|
|
|
|
if (zend_get_parameters_ex(1, &encoding)==FAILURE) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
id = PGG(default_link);
|
2000-07-29 14:07:26 +08:00
|
|
|
CHECK_DEFAULT_LINK(id);
|
2000-07-02 16:59:44 +08:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if (zend_get_parameters_ex(2, &pgsql_link, &encoding)==FAILURE) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
break;
|
|
|
|
}
|
2002-04-25 15:09:45 +08:00
|
|
|
|
2000-07-02 16:59:44 +08:00
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
|
|
|
convert_to_string_ex(encoding);
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_LVAL_P(return_value) = PQsetClientEncoding(pgsql, Z_STRVAL_PP(encoding));
|
|
|
|
Z_TYPE_P(return_value) = IS_LONG;
|
2002-04-25 15:09:45 +08:00
|
|
|
|
2000-07-02 16:59:44 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-10 14:14:03 +08:00
|
|
|
/* {{{ proto string pg_client_encoding([resource connection])
|
2000-07-02 16:59:44 +08:00
|
|
|
Get the current client encoding */
|
2000-09-13 12:13:36 +08:00
|
|
|
PHP_FUNCTION(pg_client_encoding)
|
2000-07-02 16:59:44 +08:00
|
|
|
{
|
2000-07-29 14:07:26 +08:00
|
|
|
zval **pgsql_link = NULL;
|
2000-07-02 16:59:44 +08:00
|
|
|
int id = -1;
|
|
|
|
PGconn *pgsql;
|
|
|
|
|
|
|
|
switch(ZEND_NUM_ARGS()) {
|
|
|
|
case 0:
|
|
|
|
id = PGG(default_link);
|
2000-07-29 14:07:26 +08:00
|
|
|
CHECK_DEFAULT_LINK(id);
|
2000-07-02 16:59:44 +08:00
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if (zend_get_parameters_ex(1, &pgsql_link)==FAILURE) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
2000-07-29 12:24:11 +08:00
|
|
|
/* Just do the same as found in PostgreSQL sources... */
|
|
|
|
|
|
|
|
#ifndef HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT
|
|
|
|
#define pg_encoding_to_char(x) "SQL_ASCII"
|
|
|
|
#endif
|
|
|
|
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_STRVAL_P(return_value)
|
2002-03-11 15:23:07 +08:00
|
|
|
= (char *) pg_encoding_to_char(PQclientEncoding(pgsql));
|
2001-09-26 05:58:48 +08:00
|
|
|
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
|
|
|
Z_STRVAL_P(return_value) = (char *) estrdup(Z_STRVAL_P(return_value));
|
|
|
|
Z_TYPE_P(return_value) = IS_STRING;
|
2000-07-02 16:59:44 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
2002-04-25 15:09:45 +08:00
|
|
|
#endif
|
2001-12-10 12:02:08 +08:00
|
|
|
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
#define COPYBUFSIZ 8192
|
|
|
|
|
|
|
|
/* {{{ proto bool pg_end_copy([resource connection])
|
|
|
|
Sync with backend. Completes the Copy command */
|
|
|
|
PHP_FUNCTION(pg_end_copy)
|
2001-12-10 12:02:08 +08:00
|
|
|
{
|
|
|
|
zval **pgsql_link = NULL;
|
|
|
|
int id = -1;
|
|
|
|
PGconn *pgsql;
|
2001-12-17 08:24:59 +08:00
|
|
|
int result = 0;
|
2001-12-10 12:02:08 +08:00
|
|
|
|
|
|
|
switch(ZEND_NUM_ARGS()) {
|
|
|
|
case 0:
|
|
|
|
id = PGG(default_link);
|
|
|
|
CHECK_DEFAULT_LINK(id);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if (zend_get_parameters_ex(1, &pgsql_link)==FAILURE) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
result = PQendcopy(pgsql);
|
|
|
|
|
|
|
|
if (result!=0) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed: %s", PQerrorMessage(pgsql));
|
2001-12-17 08:24:59 +08:00
|
|
|
RETURN_FALSE;
|
2002-03-11 15:23:07 +08:00
|
|
|
}
|
|
|
|
RETURN_TRUE;
|
2001-12-17 08:24:59 +08:00
|
|
|
}
|
2001-12-10 12:02:08 +08:00
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
|
|
|
|
/* {{{ proto bool pg_put_line([resource connection,] string query)
|
|
|
|
Send null-terminated string to backend server*/
|
|
|
|
PHP_FUNCTION(pg_put_line)
|
2001-12-10 12:02:08 +08:00
|
|
|
{
|
2001-12-17 08:24:59 +08:00
|
|
|
zval **query, **pgsql_link = NULL;
|
2001-12-10 12:02:08 +08:00
|
|
|
int id = -1;
|
|
|
|
PGconn *pgsql;
|
2001-12-17 08:24:59 +08:00
|
|
|
int result = 0;
|
2001-12-10 12:02:08 +08:00
|
|
|
|
|
|
|
switch(ZEND_NUM_ARGS()) {
|
2001-12-17 08:24:59 +08:00
|
|
|
case 1:
|
|
|
|
if (zend_get_parameters_ex(1, &query)==FAILURE) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2001-12-10 12:02:08 +08:00
|
|
|
id = PGG(default_link);
|
|
|
|
CHECK_DEFAULT_LINK(id);
|
|
|
|
break;
|
2001-12-17 08:24:59 +08:00
|
|
|
case 2:
|
|
|
|
if (zend_get_parameters_ex(2, &pgsql_link, &query)==FAILURE) {
|
2001-12-10 12:02:08 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
break;
|
|
|
|
}
|
2001-12-17 08:24:59 +08:00
|
|
|
|
2001-12-10 12:02:08 +08:00
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
2001-12-17 08:24:59 +08:00
|
|
|
|
|
|
|
convert_to_string_ex(query);
|
|
|
|
result = PQputline(pgsql, Z_STRVAL_PP(query));
|
|
|
|
|
|
|
|
if (result==EOF) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed: %s", PQerrorMessage(pgsql));
|
2001-12-17 08:24:59 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-01-21 08:36:22 +08:00
|
|
|
/* {{{ proto array pg_copy_to(int connection, string table_name [, string delimiter [, string null_as]])
|
|
|
|
Copy table to array */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_copy_to)
|
|
|
|
{
|
|
|
|
zval *pgsql_link;
|
|
|
|
char *table_name, *pg_delim = NULL, *pg_null_as = NULL;
|
|
|
|
int table_name_len, pg_delim_len, pg_null_as_len;
|
|
|
|
char *query;
|
|
|
|
char *query_template = "COPY \"\" TO STDOUT DELIMITERS ':' WITH NULL AS ''";
|
|
|
|
int id = -1;
|
|
|
|
PGconn *pgsql;
|
|
|
|
PGresult *pgsql_result;
|
|
|
|
ExecStatusType status;
|
|
|
|
int copydone = 0;
|
|
|
|
char copybuf[COPYBUFSIZ];
|
|
|
|
char *csv = (char *)NULL;
|
|
|
|
int ret;
|
|
|
|
int argc = ZEND_NUM_ARGS();
|
|
|
|
|
|
|
|
if (zend_parse_parameters(argc TSRMLS_CC, "rs|ss",
|
|
|
|
&pgsql_link, &table_name, &table_name_len,
|
|
|
|
&pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len) == FAILURE) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!pg_delim) {
|
|
|
|
pg_delim = "\t";
|
|
|
|
}
|
|
|
|
if (!pg_null_as) {
|
|
|
|
pg_null_as = safe_estrdup("\\\\N");
|
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
|
|
|
query = (char *)emalloc(strlen(query_template) + strlen(table_name) + strlen(pg_null_as) + 1);
|
|
|
|
sprintf(query, "COPY \"%s\" TO STDOUT DELIMITERS '%s' WITH NULL AS '%s'",
|
2002-03-11 15:23:07 +08:00
|
|
|
table_name, pg_delim, pg_null_as);
|
2001-12-17 08:24:59 +08:00
|
|
|
|
|
|
|
while ((pgsql_result = PQgetResult(pgsql))) {
|
|
|
|
PQclear(pgsql_result);
|
|
|
|
}
|
|
|
|
pgsql_result = PQexec(pgsql, query);
|
|
|
|
|
|
|
|
efree(pg_null_as);
|
|
|
|
efree(query);
|
|
|
|
|
|
|
|
if (pgsql_result) {
|
|
|
|
status = PQresultStatus(pgsql_result);
|
|
|
|
} else {
|
|
|
|
status = (ExecStatusType) PQstatus(pgsql);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (status) {
|
|
|
|
case PGRES_COPY_OUT:
|
|
|
|
if (pgsql_result) {
|
|
|
|
PQclear(pgsql_result);
|
|
|
|
if (array_init(return_value) == FAILURE) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
while (!copydone)
|
|
|
|
{
|
|
|
|
if ((ret = PQgetline(pgsql, copybuf, COPYBUFSIZ))) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed: %s", PQerrorMessage(pgsql));
|
2001-12-17 08:24:59 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (copybuf[0] == '\\' &&
|
|
|
|
copybuf[1] == '.' &&
|
|
|
|
copybuf[2] == '\0')
|
|
|
|
{
|
|
|
|
copydone = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (csv == (char *)NULL) {
|
|
|
|
csv = estrdup(copybuf);
|
|
|
|
} else {
|
|
|
|
csv = (char *)erealloc(csv, strlen(csv) + sizeof(char)*(COPYBUFSIZ+1));
|
|
|
|
strcat(csv, copybuf);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (ret)
|
|
|
|
{
|
|
|
|
case EOF:
|
|
|
|
copydone = 1;
|
|
|
|
case 0:
|
|
|
|
add_next_index_string(return_value, csv, 1);
|
|
|
|
efree(csv);
|
|
|
|
csv = (char *)NULL;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (PQendcopy(pgsql)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed: %s", PQerrorMessage(pgsql));
|
2001-12-17 08:24:59 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
while ((pgsql_result = PQgetResult(pgsql))) {
|
|
|
|
PQclear(pgsql_result);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PQclear(pgsql_result);
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
PQclear(pgsql_result);
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed: %s", PQerrorMessage(pgsql));
|
2001-12-17 08:24:59 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-01-21 08:36:22 +08:00
|
|
|
/* {{{ proto bool pg_copy_from(int connection, string table_name , array rows [, string delimiter [, string null_as]])
|
|
|
|
Copy table from array */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_copy_from)
|
|
|
|
{
|
|
|
|
zval *pgsql_link = NULL, *pg_rows;
|
|
|
|
zval **tmp;
|
|
|
|
char *table_name, *pg_delim = NULL, *pg_null_as = NULL;
|
|
|
|
int table_name_len, pg_delim_len, pg_null_as_len;
|
|
|
|
char *query;
|
|
|
|
char *query_template = "COPY \"\" FROM STDIN DELIMITERS ':' WITH NULL AS ''";
|
|
|
|
HashPosition pos;
|
|
|
|
int id = -1;
|
|
|
|
PGconn *pgsql;
|
|
|
|
PGresult *pgsql_result;
|
|
|
|
ExecStatusType status;
|
|
|
|
int argc = ZEND_NUM_ARGS();
|
|
|
|
|
|
|
|
if (zend_parse_parameters(argc TSRMLS_CC, "rs/a|ss",
|
|
|
|
&pgsql_link, &table_name, &table_name_len, &pg_rows,
|
|
|
|
&pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len) == FAILURE) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!pg_delim) {
|
|
|
|
pg_delim = "\t";
|
|
|
|
}
|
|
|
|
if (!pg_null_as) {
|
|
|
|
pg_null_as = safe_estrdup("\\\\N");
|
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
|
|
|
query = (char *)emalloc(strlen(query_template) + strlen(table_name) + strlen(pg_null_as) + 1);
|
|
|
|
sprintf(query, "COPY \"%s\" FROM STDIN DELIMITERS '%s' WITH NULL AS '%s'",
|
2002-03-11 15:23:07 +08:00
|
|
|
table_name, pg_delim, pg_null_as);
|
2001-12-17 08:24:59 +08:00
|
|
|
while ((pgsql_result = PQgetResult(pgsql))) {
|
|
|
|
PQclear(pgsql_result);
|
|
|
|
}
|
|
|
|
pgsql_result = PQexec(pgsql, query);
|
|
|
|
|
|
|
|
efree(pg_null_as);
|
|
|
|
efree(query);
|
|
|
|
|
|
|
|
if (pgsql_result) {
|
|
|
|
status = PQresultStatus(pgsql_result);
|
|
|
|
} else {
|
|
|
|
status = (ExecStatusType) PQstatus(pgsql);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (status) {
|
|
|
|
case PGRES_COPY_IN:
|
|
|
|
if (pgsql_result) {
|
|
|
|
PQclear(pgsql_result);
|
|
|
|
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(pg_rows), &pos);
|
|
|
|
while (zend_hash_get_current_data_ex(Z_ARRVAL_P(pg_rows), (void **) &tmp, &pos) == SUCCESS) {
|
|
|
|
convert_to_string_ex(tmp);
|
|
|
|
query = (char *)emalloc(Z_STRLEN_PP(tmp) +2);
|
|
|
|
strcpy(query, Z_STRVAL_PP(tmp));
|
|
|
|
if(*(query+Z_STRLEN_PP(tmp)-1) != '\n') strcat(query, "\n");
|
|
|
|
if (PQputline(pgsql, query)) {
|
|
|
|
efree(query);
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed: %s", PQerrorMessage(pgsql));
|
2001-12-17 08:24:59 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
efree(query);
|
|
|
|
zend_hash_move_forward_ex(Z_ARRVAL_P(pg_rows), &pos);
|
|
|
|
}
|
|
|
|
if (PQputline(pgsql, "\\.\n")) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed: %s", PQerrorMessage(pgsql));
|
2001-12-17 08:24:59 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
if (PQendcopy(pgsql)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed: %s", PQerrorMessage(pgsql));
|
2001-12-17 08:24:59 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
while ((pgsql_result = PQgetResult(pgsql))) {
|
|
|
|
PQclear(pgsql_result);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PQclear(pgsql_result);
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
RETURN_TRUE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
PQclear(pgsql_result);
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed: %s", PQerrorMessage(pgsql));
|
2001-12-17 08:24:59 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-03-29 19:24:54 +08:00
|
|
|
#ifdef HAVE_PQESCAPE
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto string pg_escape_string(string data)
|
|
|
|
Escape string for text/char type */
|
|
|
|
PHP_FUNCTION(pg_escape_string)
|
|
|
|
{
|
|
|
|
char *from = NULL, *to = NULL;
|
2002-04-04 21:54:51 +08:00
|
|
|
size_t from_len, to_len;
|
2001-12-17 08:24:59 +08:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
|
2002-04-04 21:54:51 +08:00
|
|
|
&from, &from_len) == FAILURE) {
|
2001-12-17 08:24:59 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-04-04 21:54:51 +08:00
|
|
|
to = (char *)emalloc(from_len*2+1);
|
|
|
|
to_len = (int)PQescapeString(to, from, from_len);
|
|
|
|
RETURN_STRINGL(to, to_len, 0);
|
2001-12-17 08:24:59 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto string pg_escape_bytea(string data)
|
|
|
|
Escape binary for bytea type */
|
|
|
|
PHP_FUNCTION(pg_escape_bytea)
|
|
|
|
{
|
|
|
|
char *from = NULL, *to = NULL;
|
2002-04-04 21:54:51 +08:00
|
|
|
size_t from_len, to_len;
|
2001-12-17 08:24:59 +08:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
|
2002-04-04 21:54:51 +08:00
|
|
|
&from, &from_len) == FAILURE) {
|
2001-12-17 08:24:59 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-04-04 21:54:51 +08:00
|
|
|
to = (char *)PQescapeBytea((unsigned char*)from, from_len, &to_len);
|
|
|
|
RETVAL_STRINGL(to, to_len-1, 1); /* to_len includes addtional '\0' */
|
2002-04-04 18:25:12 +08:00
|
|
|
free(to);
|
2001-12-17 08:24:59 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* {{{ proto string pg_result_error(resource result)
|
|
|
|
Get error message associated with result */
|
|
|
|
PHP_FUNCTION(pg_result_error)
|
|
|
|
{
|
|
|
|
zval *result;
|
|
|
|
PGresult *pgsql_result;
|
|
|
|
pgsql_result_handle *pg_result;
|
2002-03-29 19:24:54 +08:00
|
|
|
char *err = NULL;
|
2001-12-17 08:24:59 +08:00
|
|
|
|
2002-08-25 06:28:28 +08:00
|
|
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
|
|
|
|
&result) == FAILURE) {
|
|
|
|
RETURN_FALSE;
|
2001-12-17 08:24:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
|
|
|
|
|
|
|
|
pgsql_result = pg_result->result;
|
|
|
|
if (!pgsql_result) {
|
2002-03-11 15:23:07 +08:00
|
|
|
RETURN_FALSE;
|
2001-12-17 08:24:59 +08:00
|
|
|
}
|
2002-03-29 19:24:54 +08:00
|
|
|
err = (char *)PQresultErrorMessage(pgsql_result);
|
|
|
|
RETURN_STRING(err,1);
|
2001-12-17 08:24:59 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto int pg_connection_status(resource connnection)
|
|
|
|
Get connection status */
|
|
|
|
PHP_FUNCTION(pg_connection_status)
|
|
|
|
{
|
|
|
|
zval *pgsql_link = NULL;
|
|
|
|
int id = -1;
|
|
|
|
PGconn *pgsql;
|
|
|
|
|
2002-08-25 06:28:28 +08:00
|
|
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
|
|
|
|
&pgsql_link) == FAILURE) {
|
|
|
|
RETURN_FALSE;
|
2001-12-17 08:24:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
|
|
|
RETURN_LONG(PQstatus(pgsql));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto bool pg_connection_reset(resource connection)
|
|
|
|
Reset connection (reconnect) */
|
|
|
|
PHP_FUNCTION(pg_connection_reset)
|
|
|
|
{
|
|
|
|
zval *pgsql_link;
|
|
|
|
int id = -1;
|
|
|
|
PGconn *pgsql;
|
|
|
|
|
2002-08-25 06:28:28 +08:00
|
|
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
|
|
|
|
&pgsql_link) == FAILURE) {
|
|
|
|
RETURN_FALSE;
|
2001-12-17 08:24:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
2001-12-10 12:02:08 +08:00
|
|
|
PQreset(pgsql);
|
|
|
|
if (PQstatus(pgsql) == CONNECTION_BAD) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
#define PHP_PG_ASYNC_IS_BUSY 1
|
|
|
|
#define PHP_PG_ASYNC_REQUEST_CANCEL 2
|
2002-04-08 09:37:38 +08:00
|
|
|
|
|
|
|
/* {{{ php_pgsql_flush_query
|
|
|
|
*/
|
2002-04-08 10:01:45 +08:00
|
|
|
static int php_pgsql_flush_query(PGconn *pgsql TSRMLS_DC)
|
2002-04-08 09:37:38 +08:00
|
|
|
{
|
|
|
|
PGresult *res;
|
|
|
|
int leftover = 0;
|
|
|
|
|
|
|
|
if (PQsetnonblocking(pgsql, 1)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to nonblocking mode");
|
2002-04-08 09:37:38 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
while ((res = PQgetResult(pgsql))) {
|
|
|
|
PQclear(res);
|
|
|
|
leftover++;
|
|
|
|
}
|
|
|
|
PQsetnonblocking(pgsql, 0);
|
|
|
|
return leftover;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-10 12:02:08 +08:00
|
|
|
/* {{{ php_pgsql_do_async
|
|
|
|
*/
|
2002-02-06 15:16:10 +08:00
|
|
|
static void php_pgsql_do_async(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
|
2001-12-10 12:02:08 +08:00
|
|
|
{
|
2001-12-17 08:24:59 +08:00
|
|
|
zval *pgsql_link;
|
2001-12-10 12:02:08 +08:00
|
|
|
int id = -1;
|
|
|
|
PGconn *pgsql;
|
|
|
|
PGresult *pgsql_result;
|
|
|
|
|
2002-08-25 06:28:28 +08:00
|
|
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
|
|
|
|
&pgsql_link) == FAILURE) {
|
|
|
|
RETURN_FALSE;
|
2001-12-10 12:02:08 +08:00
|
|
|
}
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
2001-12-10 12:02:08 +08:00
|
|
|
|
2002-03-29 19:24:54 +08:00
|
|
|
if (PQ_SETNONBLOCKING(pgsql, 1)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to nonblocking mode");
|
2001-12-19 13:41:26 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2001-12-10 12:02:08 +08:00
|
|
|
switch(entry_type) {
|
|
|
|
case PHP_PG_ASYNC_IS_BUSY:
|
|
|
|
PQconsumeInput(pgsql);
|
|
|
|
Z_LVAL_P(return_value) = PQisBusy(pgsql);
|
|
|
|
Z_TYPE_P(return_value) = IS_LONG;
|
|
|
|
break;
|
|
|
|
case PHP_PG_ASYNC_REQUEST_CANCEL:
|
|
|
|
Z_LVAL_P(return_value) = PQrequestCancel(pgsql);
|
|
|
|
Z_TYPE_P(return_value) = IS_LONG;
|
|
|
|
while ((pgsql_result = PQgetResult(pgsql))) {
|
|
|
|
PQclear(pgsql_result);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_ERROR,"PostgreSQL module error. Report this error");
|
2001-12-10 12:02:08 +08:00
|
|
|
break;
|
|
|
|
}
|
2002-03-29 19:24:54 +08:00
|
|
|
if (PQ_SETNONBLOCKING(pgsql, 0)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to blocking mode");
|
2001-12-19 13:41:26 +08:00
|
|
|
}
|
2001-12-10 12:02:08 +08:00
|
|
|
convert_to_boolean_ex(&return_value);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 19:53:38 +08:00
|
|
|
/* {{{ proto bool pg_cancel_query(resource connection)
|
2001-12-10 12:02:08 +08:00
|
|
|
Cancel request */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_cancel_query)
|
2001-12-10 12:02:08 +08:00
|
|
|
{
|
|
|
|
php_pgsql_do_async(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_ASYNC_REQUEST_CANCEL);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 19:53:38 +08:00
|
|
|
/* {{{ proto bool pg_connection_busy(resource connection)
|
2001-12-10 12:02:08 +08:00
|
|
|
Get connection is busy or not */
|
2001-12-17 08:24:59 +08:00
|
|
|
PHP_FUNCTION(pg_connection_busy)
|
2001-12-10 12:02:08 +08:00
|
|
|
{
|
|
|
|
php_pgsql_do_async(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_ASYNC_IS_BUSY);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
/* {{{ proto bool pg_send_query(resource connection, string qeury)
|
2001-12-10 12:02:08 +08:00
|
|
|
Send asynchronous query */
|
|
|
|
PHP_FUNCTION(pg_send_query)
|
|
|
|
{
|
2001-12-17 08:24:59 +08:00
|
|
|
zval *pgsql_link;
|
|
|
|
char *query;
|
|
|
|
int len;
|
2001-12-10 12:02:08 +08:00
|
|
|
int id = -1;
|
|
|
|
PGconn *pgsql;
|
|
|
|
PGresult *res;
|
|
|
|
int leftover = 0;
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs",
|
|
|
|
&pgsql_link, &query, &len) == FAILURE) {
|
|
|
|
return;
|
2001-12-10 12:02:08 +08:00
|
|
|
}
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
2002-03-29 19:24:54 +08:00
|
|
|
if (PQ_SETNONBLOCKING(pgsql, 1)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to nonblocking mode");
|
2001-12-10 12:02:08 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
while ((res = PQgetResult(pgsql))) {
|
|
|
|
PQclear(res);
|
|
|
|
leftover = 1;
|
|
|
|
}
|
|
|
|
if (leftover) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE,"There are results on this connection. Call pg_get_result() until it returns FALSE");
|
2001-12-10 12:02:08 +08:00
|
|
|
}
|
2001-12-17 08:24:59 +08:00
|
|
|
if (!PQsendQuery(pgsql, query)) {
|
2001-12-10 12:02:08 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2002-03-29 19:24:54 +08:00
|
|
|
if (PQ_SETNONBLOCKING(pgsql, 0)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to blocking mode");
|
2001-12-10 12:02:08 +08:00
|
|
|
}
|
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
|
2001-12-17 19:48:07 +08:00
|
|
|
/* {{{ proto resource pg_get_result([resource connection])
|
2001-12-10 12:02:08 +08:00
|
|
|
Get asynchronous query result */
|
|
|
|
PHP_FUNCTION(pg_get_result)
|
|
|
|
{
|
2001-12-17 08:24:59 +08:00
|
|
|
zval *pgsql_link;
|
2001-12-10 12:02:08 +08:00
|
|
|
int id = -1;
|
|
|
|
PGconn *pgsql;
|
|
|
|
PGresult *pgsql_result;
|
|
|
|
pgsql_result_handle *pg_result;
|
|
|
|
|
2002-08-25 06:28:28 +08:00
|
|
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
|
|
|
|
&pgsql_link) == FAILURE) {
|
|
|
|
RETURN_FALSE;
|
2001-12-10 12:02:08 +08:00
|
|
|
}
|
|
|
|
|
2001-12-17 08:24:59 +08:00
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
2001-12-10 12:02:08 +08:00
|
|
|
pgsql_result = PQgetResult(pgsql);
|
|
|
|
if (!pgsql_result) {
|
|
|
|
/* no result */
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle));
|
|
|
|
pg_result->conn = pgsql;
|
|
|
|
pg_result->result = pgsql_result;
|
|
|
|
pg_result->row = -1;
|
|
|
|
ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-04-08 08:43:58 +08:00
|
|
|
/* {{{ proto int pg_result_status(resource result[, long result_type])
|
2001-12-17 08:24:59 +08:00
|
|
|
Get status of query result */
|
|
|
|
PHP_FUNCTION(pg_result_status)
|
|
|
|
{
|
|
|
|
zval *result;
|
2002-04-08 08:43:58 +08:00
|
|
|
long result_type = PGSQL_STATUS_LONG;
|
2001-12-17 08:24:59 +08:00
|
|
|
ExecStatusType status;
|
|
|
|
PGresult *pgsql_result;
|
|
|
|
pgsql_result_handle *pg_result;
|
|
|
|
|
2002-08-24 15:18:15 +08:00
|
|
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r|l",
|
2002-08-25 06:28:28 +08:00
|
|
|
&result, &result_type) == FAILURE) {
|
2002-08-24 15:18:15 +08:00
|
|
|
RETURN_FALSE;
|
2001-12-17 08:24:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
|
|
|
|
|
|
|
|
pgsql_result = pg_result->result;
|
2002-04-08 08:43:58 +08:00
|
|
|
if (result_type == PGSQL_STATUS_LONG) {
|
|
|
|
status = PQresultStatus(pgsql_result);
|
|
|
|
RETURN_LONG((int)status);
|
|
|
|
}
|
2002-04-08 08:50:44 +08:00
|
|
|
else if (result_type == PGSQL_STATUS_STRING) {
|
|
|
|
RETURN_STRING(PQcmdStatus(pgsql_result), 1);
|
|
|
|
}
|
2002-04-08 08:43:58 +08:00
|
|
|
else {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expects optional 2nd parameter to be PGSQL_STATUS_LONG or PGSQL_STATUS_STRING");
|
2002-04-08 08:43:58 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2001-12-17 08:24:59 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-04-08 09:37:38 +08:00
|
|
|
#define QUERY_BUF_SIZE (1023)
|
|
|
|
|
|
|
|
/* {{{ php_pgsql_metadata
|
|
|
|
|
|
|
|
*/
|
|
|
|
PHPAPI int php_pgsql_metadata(PGconn *pg_link, const char *table_name, zval *meta TSRMLS_DC)
|
|
|
|
{
|
|
|
|
PGresult *pg_result;
|
2002-04-21 19:29:17 +08:00
|
|
|
char *tmp_name;
|
|
|
|
smart_str querystr = {0};
|
2002-04-08 09:37:38 +08:00
|
|
|
size_t new_len;
|
|
|
|
int i, num_rows;
|
|
|
|
zval *elem;
|
|
|
|
|
2002-04-21 19:29:17 +08:00
|
|
|
smart_str_appends(&querystr,
|
|
|
|
"SELECT a.attname, a.attnum, t.typname, a.attlen, a.attnotNULL, a.atthasdef "
|
|
|
|
"FROM pg_class as c, pg_attribute a, pg_type t "
|
|
|
|
"WHERE a.attnum > 0 AND a.attrelid = c.oid AND c.relname = '");
|
|
|
|
|
2002-04-08 09:37:38 +08:00
|
|
|
tmp_name = php_addslashes((char *)table_name, strlen(table_name), &new_len, 0 TSRMLS_CC);
|
2002-04-21 19:29:17 +08:00
|
|
|
smart_str_appendl(&querystr, tmp_name, new_len);
|
2002-04-08 09:37:38 +08:00
|
|
|
efree(tmp_name);
|
2002-04-21 19:29:17 +08:00
|
|
|
|
|
|
|
smart_str_appends(&querystr, "' AND a.atttypid = t.oid ORDER BY a.attnum;");
|
|
|
|
smart_str_0(&querystr);
|
|
|
|
|
|
|
|
pg_result = PQexec(pg_link, querystr.c);
|
2002-04-08 09:37:38 +08:00
|
|
|
if (PQresultStatus(pg_result) != PGRES_TUPLES_OK || (num_rows = PQntuples(pg_result)) == 0) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Failed to query metadata for '%s' table %s", table_name, querystr.c);
|
2002-04-21 19:29:17 +08:00
|
|
|
smart_str_free(&querystr);
|
2002-04-08 09:37:38 +08:00
|
|
|
PQclear(pg_result);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
2002-04-21 19:29:17 +08:00
|
|
|
smart_str_free(&querystr);
|
2002-04-08 09:37:38 +08:00
|
|
|
|
|
|
|
for (i = 0; i < num_rows; i++) {
|
|
|
|
char *name;
|
|
|
|
MAKE_STD_ZVAL(elem);
|
|
|
|
array_init(elem);
|
|
|
|
add_assoc_long(elem, "num", atoi(PQgetvalue(pg_result,i,1)));
|
|
|
|
add_assoc_string(elem, "type", PQgetvalue(pg_result,i,2), 1);
|
|
|
|
add_assoc_long(elem, "len", atoi(PQgetvalue(pg_result,i,3)));
|
|
|
|
if (!strcmp(PQgetvalue(pg_result,i,4), "t")) {
|
|
|
|
add_assoc_bool(elem, "not null", 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
add_assoc_bool(elem, "not null", 0);
|
|
|
|
}
|
|
|
|
if (!strcmp(PQgetvalue(pg_result,i,5), "t")) {
|
2002-04-19 20:19:29 +08:00
|
|
|
add_assoc_bool(elem, "has default", 1);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
else {
|
2002-04-19 20:19:29 +08:00
|
|
|
add_assoc_bool(elem, "has default", 0);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
name = PQgetvalue(pg_result,i,0);
|
|
|
|
add_assoc_zval(meta, name, elem);
|
|
|
|
}
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
|
|
|
|
/* {{{ proto array pg_metadata(resource db, string table)
|
|
|
|
Get metadata */
|
|
|
|
PHP_FUNCTION(pg_metadata)
|
|
|
|
{
|
|
|
|
zval *pgsql_link;
|
|
|
|
char *table_name;
|
|
|
|
uint table_name_len;
|
|
|
|
PGconn *pgsql;
|
|
|
|
int id = -1;
|
|
|
|
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs",
|
|
|
|
&pgsql_link, &table_name, &table_name_len) == FAILURE) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
|
|
|
array_init(return_value);
|
|
|
|
if (php_pgsql_metadata(pgsql, table_name, return_value TSRMLS_CC) == FAILURE) {
|
|
|
|
zval_dtor(return_value); /* destroy array */
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ php_pgsql_get_data_type
|
|
|
|
*/
|
|
|
|
static php_pgsql_data_type php_pgsql_get_data_type(const char *type_name, size_t len)
|
|
|
|
{
|
|
|
|
/* This is stupid way to do. I'll fix it when I decied how to support
|
|
|
|
user defined types. (Yasuo) */
|
|
|
|
|
|
|
|
/* boolean */
|
2002-07-20 15:24:15 +08:00
|
|
|
if (!strcmp(type_name, "bool")|| !strcmp(type_name, "boolean"))
|
2002-04-08 09:37:38 +08:00
|
|
|
return PG_BOOL;
|
|
|
|
/* object id */
|
|
|
|
if (!strcmp(type_name, "oid"))
|
|
|
|
return PG_OID;
|
|
|
|
/* integer */
|
|
|
|
if (!strcmp(type_name, "int2") || !strcmp(type_name, "smallint"))
|
|
|
|
return PG_INT2;
|
|
|
|
if (!strcmp(type_name, "int4") || !strcmp(type_name, "integer"))
|
|
|
|
return PG_INT4;
|
|
|
|
if (!strcmp(type_name, "int8") || !strcmp(type_name, "bigint"))
|
|
|
|
return PG_INT8;
|
|
|
|
/* real and other */
|
|
|
|
if (!strcmp(type_name, "float4") || !strcmp(type_name, "real"))
|
|
|
|
return PG_FLOAT4;
|
|
|
|
if (!strcmp(type_name, "float8") || !strcmp(type_name, "double precision"))
|
|
|
|
return PG_FLOAT8;
|
|
|
|
if (!strcmp(type_name, "numeric"))
|
|
|
|
return PG_NUMERIC;
|
|
|
|
if (!strcmp(type_name, "money"))
|
|
|
|
return PG_MONEY;
|
|
|
|
/* character */
|
|
|
|
if (!strcmp(type_name, "text"))
|
|
|
|
return PG_TEXT;
|
|
|
|
if (!strcmp(type_name, "bpchar") || !strcmp(type_name, "character"))
|
|
|
|
return PG_CHAR;
|
|
|
|
if (!strcmp(type_name, "varchar") || !strcmp(type_name, "character varying"))
|
|
|
|
return PG_VARCHAR;
|
|
|
|
/* time and interval */
|
|
|
|
if (!strcmp(type_name, "abstime"))
|
|
|
|
return PG_UNIX_TIME;
|
|
|
|
if (!strcmp(type_name, "reltime"))
|
|
|
|
return PG_UNIX_TIME_INTERVAL;
|
|
|
|
if (!strcmp(type_name, "tinterval"))
|
|
|
|
return PG_UNIX_TIME_INTERVAL;
|
|
|
|
if (!strcmp(type_name, "date"))
|
|
|
|
return PG_DATE;
|
|
|
|
if (!strcmp(type_name, "time"))
|
|
|
|
return PG_TIME;
|
|
|
|
if (!strcmp(type_name, "timestamp") || !strcmp(type_name, "time with time zone"))
|
|
|
|
return PG_TIME_WITH_TIMEZONE;
|
|
|
|
if (!strcmp(type_name, "timestamp with time zone"))
|
|
|
|
return PG_TIMESTAMP_WITH_TIMEZONE;
|
|
|
|
if (!strcmp(type_name, "interval"))
|
|
|
|
return PG_INTERVAL;
|
|
|
|
/* binary */
|
|
|
|
if (!strcmp(type_name, "bytea"))
|
|
|
|
return PG_BYTEA;
|
|
|
|
/* network */
|
|
|
|
if (!strcmp(type_name, "cidr"))
|
|
|
|
return PG_CIDR;
|
|
|
|
if (!strcmp(type_name, "inet"))
|
|
|
|
return PG_INET;
|
|
|
|
if (!strcmp(type_name, "macaddr"))
|
|
|
|
return PG_MACADDR;
|
|
|
|
/* bit */
|
|
|
|
if (!strcmp(type_name, "bit"))
|
|
|
|
return PG_BIT;
|
|
|
|
if (!strcmp(type_name, "bit varying"))
|
|
|
|
return PG_VARBIT;
|
2002-04-21 18:37:40 +08:00
|
|
|
/* geometric */
|
2002-04-08 09:37:38 +08:00
|
|
|
if (!strcmp(type_name, "line"))
|
|
|
|
return PG_LINE;
|
|
|
|
if (!strcmp(type_name, "lseg"))
|
|
|
|
return PG_LSEG;
|
|
|
|
if (!strcmp(type_name, "box"))
|
|
|
|
return PG_BOX;
|
|
|
|
if (!strcmp(type_name, "path"))
|
|
|
|
return PG_PATH;
|
|
|
|
if (!strcmp(type_name, "point"))
|
|
|
|
return PG_POINT;
|
|
|
|
if (!strcmp(type_name, "polygon"))
|
|
|
|
return PG_POLYGON;
|
|
|
|
if (!strcmp(type_name, "circle"))
|
|
|
|
return PG_CIRCLE;
|
|
|
|
|
|
|
|
return PG_UNKNOWN;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ php_pgsql_convert_match
|
|
|
|
* test field value with regular expression specified.
|
|
|
|
*/
|
|
|
|
static int php_pgsql_convert_match(const char *str, const char *regex , int icase TSRMLS_DC)
|
|
|
|
{
|
|
|
|
regex_t re;
|
|
|
|
regmatch_t *subs;
|
|
|
|
int regopt = REG_EXTENDED;
|
|
|
|
int regerr, ret = SUCCESS;
|
|
|
|
|
|
|
|
if (icase) {
|
|
|
|
regopt |= REG_ICASE;
|
|
|
|
}
|
|
|
|
|
|
|
|
regerr = regcomp(&re, regex, regopt);
|
|
|
|
if (regerr) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot compile regex");
|
2002-04-08 09:37:38 +08:00
|
|
|
regfree(&re);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
subs = (regmatch_t *)ecalloc(sizeof(regmatch_t), re.re_nsub+1);
|
|
|
|
if (!subs) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot allocate memory");
|
2002-04-08 09:37:38 +08:00
|
|
|
regfree(&re);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
regerr = regexec(&re, str, re.re_nsub+1, subs, 0);
|
|
|
|
if (regerr == REG_NOMATCH) {
|
|
|
|
#ifdef PHP_DEBUG
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "'%s' does not match with '%s'", str, regex);
|
2002-04-08 09:37:38 +08:00
|
|
|
#endif
|
|
|
|
ret = FAILURE;
|
|
|
|
}
|
|
|
|
else if (regerr) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot exec regex");
|
2002-04-08 09:37:38 +08:00
|
|
|
ret = FAILURE;
|
|
|
|
}
|
|
|
|
regfree(&re);
|
|
|
|
efree(subs);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* }}} */
|
|
|
|
|
2002-04-19 20:19:29 +08:00
|
|
|
/* {{{ php_pgsql_add_quote
|
2002-04-08 09:37:38 +08:00
|
|
|
* add quotes around string.
|
|
|
|
*/
|
2002-04-08 10:01:45 +08:00
|
|
|
static int php_pgsql_add_quotes(zval *src, zend_bool should_free TSRMLS_DC)
|
2002-04-08 09:37:38 +08:00
|
|
|
{
|
2002-04-21 19:29:17 +08:00
|
|
|
smart_str str = {0};
|
|
|
|
|
2002-04-08 09:37:38 +08:00
|
|
|
assert(Z_TYPE_P(src) == IS_STRING);
|
|
|
|
assert(should_free == 1 || should_free == 0);
|
|
|
|
|
2002-04-21 19:29:17 +08:00
|
|
|
smart_str_appendc(&str, '\'');
|
|
|
|
smart_str_appendl(&str, Z_STRVAL_P(src), Z_STRLEN_P(src));
|
|
|
|
smart_str_appendc(&str, '\'');
|
|
|
|
smart_str_0(&str);
|
|
|
|
|
2002-04-08 09:37:38 +08:00
|
|
|
if (should_free) {
|
|
|
|
efree(Z_STRVAL_P(src));
|
|
|
|
}
|
2002-04-21 19:29:17 +08:00
|
|
|
Z_STRVAL_P(src) = str.c;
|
|
|
|
Z_STRLEN_P(src) = str.len;
|
2002-04-08 09:37:38 +08:00
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-04-23 11:42:26 +08:00
|
|
|
#define PGSQL_CONV_CHECK_IGNORE() \
|
2002-07-20 14:45:35 +08:00
|
|
|
if (!err && Z_TYPE_P(new_val) == IS_STRING && !strcmp(Z_STRVAL_P(new_val), "NULL")) { \
|
2002-04-23 11:42:26 +08:00
|
|
|
/* if value is NULL and has default, remove entry to use default value*/ \
|
|
|
|
if (!(opt & PGSQL_CONV_IGNORE_DEFAULT) && Z_BVAL_PP(has_default)) { \
|
|
|
|
zval_dtor(new_val); \
|
|
|
|
FREE_ZVAL(new_val); \
|
|
|
|
skip_field = 1; \
|
|
|
|
} \
|
|
|
|
/* raise error if it's not null */ \
|
|
|
|
else if (Z_BVAL_PP(not_null)) { \
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected NULL for 'NOT NULL' field '%s'", field ); \
|
2002-04-23 11:42:26 +08:00
|
|
|
err = 1; \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
2002-04-08 09:37:38 +08:00
|
|
|
/* {{{ php_pgsql_convert
|
|
|
|
* check and convert array values (fieldname=>vlaue pair) for sql
|
|
|
|
*/
|
2002-04-23 11:42:26 +08:00
|
|
|
PHPAPI int php_pgsql_convert(PGconn *pg_link, const char *table_name, const zval *values, zval *result, ulong opt TSRMLS_DC)
|
2002-04-08 09:37:38 +08:00
|
|
|
{
|
|
|
|
HashPosition pos;
|
|
|
|
char *field = NULL;
|
|
|
|
uint field_len = -1;
|
|
|
|
ulong num_idx = -1;
|
2002-04-19 20:24:14 +08:00
|
|
|
zval *meta, **def, **type, **not_null, **has_default, **val, *new_val;
|
|
|
|
int new_len, key_type, err = 0, skip_field;
|
2002-04-08 09:37:38 +08:00
|
|
|
|
|
|
|
assert(pg_link != NULL);
|
|
|
|
assert(Z_TYPE_P(values) == IS_ARRAY);
|
|
|
|
assert(Z_TYPE_P(result) == IS_ARRAY);
|
2002-04-23 11:42:26 +08:00
|
|
|
assert(!(opt & ~PGSQL_CONV_OPTS));
|
2002-04-08 09:37:38 +08:00
|
|
|
|
|
|
|
if (!table_name) {
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
MAKE_STD_ZVAL(meta);
|
|
|
|
if (array_init(meta) == FAILURE) {
|
|
|
|
zval_dtor(meta);
|
|
|
|
FREE_ZVAL(meta);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
if (php_pgsql_metadata(pg_link, table_name, meta TSRMLS_CC) == FAILURE) {
|
|
|
|
zval_dtor(meta);
|
|
|
|
FREE_ZVAL(meta);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos);
|
|
|
|
zend_hash_get_current_data_ex(Z_ARRVAL_P(values), (void **)&val, &pos) == SUCCESS;
|
|
|
|
zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos)) {
|
2002-04-19 20:24:14 +08:00
|
|
|
skip_field = 0;
|
2002-04-21 18:37:40 +08:00
|
|
|
if ((key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(values), &field, &field_len, &num_idx, 0, &pos)) == HASH_KEY_NON_EXISTANT) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to get array key type");
|
2002-04-08 09:37:38 +08:00
|
|
|
err = 1;
|
|
|
|
}
|
|
|
|
if (!err && key_type == HASH_KEY_IS_LONG) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Accepts only string key for values");
|
2002-04-08 09:37:38 +08:00
|
|
|
err = 1;
|
|
|
|
}
|
|
|
|
if (!err && key_type == HASH_KEY_NON_EXISTANT) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Accepts only string key for values");
|
2002-04-08 09:37:38 +08:00
|
|
|
err = 1;
|
|
|
|
}
|
|
|
|
if (!err && zend_hash_find(Z_ARRVAL_P(meta), field, field_len, (void **)&def) == FAILURE) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid field name (%s) in values", field);
|
2002-04-08 09:37:38 +08:00
|
|
|
err = 1;
|
|
|
|
}
|
2002-04-19 20:24:14 +08:00
|
|
|
if (!err && zend_hash_find(Z_ARRVAL_PP(def), "type", sizeof("type"), (void **)&type) == FAILURE) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected broken meta data. Missing 'type'");
|
2002-04-19 20:24:14 +08:00
|
|
|
err = 1;
|
|
|
|
}
|
|
|
|
if (!err && zend_hash_find(Z_ARRVAL_PP(def), "not null", sizeof("not null"), (void **)¬_null) == FAILURE) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected broken meta data. Missing 'not null'");
|
2002-04-19 20:24:14 +08:00
|
|
|
err = 1;
|
|
|
|
}
|
|
|
|
if (!err && zend_hash_find(Z_ARRVAL_PP(def), "has default", sizeof("has default"), (void **)&has_default) == FAILURE) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected broken meta data. Missing 'has default'");
|
2002-04-08 09:37:38 +08:00
|
|
|
err = 1;
|
|
|
|
}
|
|
|
|
if (!err && (Z_TYPE_PP(val) == IS_ARRAY ||
|
|
|
|
Z_TYPE_PP(val) == IS_OBJECT ||
|
|
|
|
Z_TYPE_PP(val) == IS_CONSTANT_ARRAY)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects scaler values as field values");
|
2002-04-08 09:37:38 +08:00
|
|
|
err = 1;
|
|
|
|
}
|
|
|
|
if (err) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
MAKE_STD_ZVAL(new_val);
|
|
|
|
switch(php_pgsql_get_data_type(Z_STRVAL_PP(type), Z_STRLEN_PP(type)))
|
|
|
|
{
|
|
|
|
case PG_BOOL:
|
|
|
|
switch (Z_TYPE_PP(val)) {
|
|
|
|
case IS_STRING:
|
|
|
|
if (Z_STRLEN_PP(val) == 0) {
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!strcmp(Z_STRVAL_PP(val), "t") || !strcmp(Z_STRVAL_PP(val), "T") ||
|
|
|
|
!strcmp(Z_STRVAL_PP(val), "y") || !strcmp(Z_STRVAL_PP(val), "Y") ||
|
|
|
|
!strcmp(Z_STRVAL_PP(val), "true") || !strcmp(Z_STRVAL_PP(val), "True") ||
|
|
|
|
!strcmp(Z_STRVAL_PP(val), "yes") || !strcmp(Z_STRVAL_PP(val), "Yes") ||
|
|
|
|
!strcmp(Z_STRVAL_PP(val), "1")) {
|
2002-07-20 15:45:01 +08:00
|
|
|
ZVAL_STRING(new_val, "'t'", 1);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
else if (!strcmp(Z_STRVAL_PP(val), "f") || !strcmp(Z_STRVAL_PP(val), "F") ||
|
|
|
|
!strcmp(Z_STRVAL_PP(val), "n") || !strcmp(Z_STRVAL_PP(val), "N") ||
|
|
|
|
!strcmp(Z_STRVAL_PP(val), "false") || !strcmp(Z_STRVAL_PP(val), "False") ||
|
|
|
|
!strcmp(Z_STRVAL_PP(val), "no") || !strcmp(Z_STRVAL_PP(val), "No") ||
|
|
|
|
!strcmp(Z_STRVAL_PP(val), "0")) {
|
2002-07-20 15:45:01 +08:00
|
|
|
ZVAL_STRING(new_val, "'f'", 1);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
else {
|
2002-09-05 06:25:13 +08:00
|
|
|
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);
|
2002-04-08 09:37:38 +08:00
|
|
|
err = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_LONG:
|
|
|
|
case IS_BOOL:
|
|
|
|
if (Z_LVAL_PP(val)) {
|
2002-07-20 15:45:01 +08:00
|
|
|
ZVAL_STRING(new_val, "'t'", 1);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
else {
|
2002-07-20 15:45:01 +08:00
|
|
|
ZVAL_STRING(new_val, "'f'", 1);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_NULL:
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
err = 1;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
PGSQL_CONV_CHECK_IGNORE();
|
2002-04-08 09:37:38 +08:00
|
|
|
if (err) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects string, null, long or boolelan value for PostgreSQL '%s' (%s)", Z_STRVAL_PP(type), field);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PG_OID:
|
|
|
|
case PG_INT2:
|
|
|
|
case PG_INT4:
|
|
|
|
case PG_INT8:
|
|
|
|
switch (Z_TYPE_PP(val)) {
|
|
|
|
case IS_STRING:
|
|
|
|
if (Z_STRLEN_PP(val) == 0) {
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* FIXME: better regex must be used */
|
2002-04-08 10:01:45 +08:00
|
|
|
if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^([+-]{0,1}[0-9]+)$", 0 TSRMLS_CC) == FAILURE) {
|
2002-04-08 09:37:38 +08:00
|
|
|
err = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_DOUBLE:
|
|
|
|
ZVAL_DOUBLE(new_val, Z_DVAL_PP(val));
|
|
|
|
convert_to_long_ex(&new_val);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_LONG:
|
|
|
|
ZVAL_LONG(new_val, Z_LVAL_PP(val));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_NULL:
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
err = 1;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
PGSQL_CONV_CHECK_IGNORE();
|
2002-04-08 09:37:38 +08:00
|
|
|
if (err) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects string, null, long or double value for pgsql '%s' (%s)", Z_STRVAL_PP(type), field);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PG_NUMERIC:
|
|
|
|
case PG_MONEY:
|
|
|
|
case PG_FLOAT4:
|
|
|
|
case PG_FLOAT8:
|
|
|
|
switch (Z_TYPE_PP(val)) {
|
|
|
|
case IS_STRING:
|
|
|
|
if (Z_STRLEN_PP(val) == 0) {
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* FIXME: better regex must be used */
|
2002-04-08 10:01:45 +08:00
|
|
|
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) {
|
2002-04-08 09:37:38 +08:00
|
|
|
err = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_LONG:
|
2002-04-20 10:31:48 +08:00
|
|
|
ZVAL_LONG(new_val, Z_LVAL_PP(val));
|
2002-04-08 09:37:38 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_DOUBLE:
|
|
|
|
ZVAL_DOUBLE(new_val, Z_DVAL_PP(val));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_NULL:
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
err = 1;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
PGSQL_CONV_CHECK_IGNORE();
|
2002-04-08 09:37:38 +08:00
|
|
|
if (err) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects string, null, long or double value for PostgreSQL '%s' (%s)", Z_STRVAL_PP(type), field);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PG_TEXT:
|
|
|
|
case PG_CHAR:
|
|
|
|
case PG_VARCHAR:
|
|
|
|
switch (Z_TYPE_PP(val)) {
|
|
|
|
case IS_STRING:
|
|
|
|
if (Z_STRLEN_PP(val) == 0) {
|
2002-07-22 14:38:36 +08:00
|
|
|
ZVAL_STRING(new_val, empty_string, 1);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
Z_TYPE_P(new_val) = IS_STRING;
|
|
|
|
#if HAVE_PQESCAPE
|
|
|
|
{
|
|
|
|
char *tmp;
|
|
|
|
tmp = (char *)emalloc(Z_STRLEN_PP(val)*2+1);
|
|
|
|
Z_STRLEN_P(new_val) = (int)PQescapeString(tmp, Z_STRVAL_PP(val), Z_STRLEN_PP(val));
|
|
|
|
Z_STRVAL_P(new_val) = tmp;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
Z_STRVAL_P(new_val) = php_addslashes(Z_STRVAL_PP(val), Z_STRLEN_PP(val), &Z_STRLEN_P(new_val), 0 TSRMLS_CC);
|
|
|
|
#endif
|
|
|
|
}
|
2002-07-20 15:08:17 +08:00
|
|
|
php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
|
2002-04-08 09:37:38 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_LONG:
|
|
|
|
ZVAL_LONG(new_val, Z_LVAL_PP(val));
|
|
|
|
convert_to_string_ex(&new_val);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_DOUBLE:
|
|
|
|
ZVAL_DOUBLE(new_val, Z_DVAL_PP(val));
|
|
|
|
convert_to_string_ex(&new_val);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_NULL:
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
err = 1;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
PGSQL_CONV_CHECK_IGNORE();
|
2002-04-08 09:37:38 +08:00
|
|
|
if (err) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects string, null, long or double value for PostgreSQL '%s' (%s)", Z_STRVAL_PP(type), field);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PG_UNIX_TIME:
|
|
|
|
case PG_UNIX_TIME_INTERVAL:
|
|
|
|
/* these are the actallay a integer */
|
|
|
|
switch (Z_TYPE_PP(val)) {
|
|
|
|
case IS_STRING:
|
|
|
|
if (Z_STRLEN_PP(val) == 0) {
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* FIXME: Better regex must be used */
|
2002-04-08 10:01:45 +08:00
|
|
|
if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^[0-9]+$", 0 TSRMLS_CC) == FAILURE) {
|
2002-04-08 09:37:38 +08:00
|
|
|
err = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
|
|
|
|
convert_to_long_ex(&new_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_DOUBLE:
|
|
|
|
ZVAL_DOUBLE(new_val, Z_DVAL_PP(val));
|
|
|
|
convert_to_long_ex(&new_val);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_LONG:
|
|
|
|
ZVAL_LONG(new_val, Z_LVAL_PP(val));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_NULL:
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
err = 1;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
PGSQL_CONV_CHECK_IGNORE();
|
2002-04-08 09:37:38 +08:00
|
|
|
if (err) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects string, null, long or double value for '%s' (%s)", Z_STRVAL_PP(type), field);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PG_CIDR:
|
|
|
|
case PG_INET:
|
|
|
|
switch (Z_TYPE_PP(val)) {
|
|
|
|
case IS_STRING:
|
|
|
|
if (Z_STRLEN_PP(val) == 0) {
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* FIXME: Better regex must be used */
|
2002-04-08 10:01:45 +08:00
|
|
|
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) {
|
2002-04-08 09:37:38 +08:00
|
|
|
err = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
|
|
|
|
php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_NULL:
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
err = 1;
|
2002-04-19 20:24:14 +08:00
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
PGSQL_CONV_CHECK_IGNORE();
|
2002-04-08 09:37:38 +08:00
|
|
|
if (err) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects string or null for '%s' (%s)", Z_STRVAL_PP(type), field);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PG_TIME_WITH_TIMEZONE:
|
|
|
|
case PG_TIMESTAMP_WITH_TIMEZONE:
|
|
|
|
switch(Z_TYPE_PP(val)) {
|
|
|
|
case IS_STRING:
|
|
|
|
if (Z_STRLEN_PP(val) == 0) {
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* FIXME: better regex must be used */
|
2002-04-08 10:01:45 +08:00
|
|
|
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,1}$", 1 TSRMLS_CC) == FAILURE) {
|
2002-04-08 09:37:38 +08:00
|
|
|
err = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
|
|
|
|
php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_NULL:
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
err = 1;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
PGSQL_CONV_CHECK_IGNORE();
|
2002-04-08 09:37:38 +08:00
|
|
|
if (err) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects string or null for PostgreSQL %s field (%s)", Z_STRVAL_PP(type), field);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PG_DATE:
|
|
|
|
switch(Z_TYPE_PP(val)) {
|
|
|
|
case IS_STRING:
|
|
|
|
if (Z_STRLEN_PP(val) == 0) {
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* FIXME: better regex must be used */
|
2002-04-08 10:01:45 +08:00
|
|
|
if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^([0-9]{4}[/-][0-9]{1,2}[/-][0-9]{1,2})$", 1 TSRMLS_CC) == FAILURE) {
|
2002-04-08 09:37:38 +08:00
|
|
|
err = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
|
|
|
|
php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_NULL:
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
err = 1;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
PGSQL_CONV_CHECK_IGNORE();
|
2002-04-08 09:37:38 +08:00
|
|
|
if (err) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects string or null for PostgreSQL %s field (%s)", Z_STRVAL_PP(type), field);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PG_TIME:
|
|
|
|
switch(Z_TYPE_PP(val)) {
|
|
|
|
case IS_STRING:
|
|
|
|
if (Z_STRLEN_PP(val) == 0) {
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* FIXME: better regex must be used */
|
2002-04-08 10:01:45 +08:00
|
|
|
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) {
|
2002-04-08 09:37:38 +08:00
|
|
|
err = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
|
|
|
|
php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_NULL:
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
err = 1;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
PGSQL_CONV_CHECK_IGNORE();
|
2002-04-08 09:37:38 +08:00
|
|
|
if (err) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects string or null for PostgreSQL %s field (%s)", Z_STRVAL_PP(type), field);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PG_INTERVAL:
|
|
|
|
switch(Z_TYPE_PP(val)) {
|
|
|
|
case IS_STRING:
|
|
|
|
if (Z_STRLEN_PP(val) == 0) {
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* FIXME: better regex must be used */
|
2002-04-08 10:01:45 +08:00
|
|
|
if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^[+-]{0,1}[ \\t]+((second|seconds|minute|minute|hour|hour|day|days|week|weeks|month|monthes|year|years|decade|decades|century|centuries|millennium|millenniums){1,1}[ \\t]+)+([ \\t]+ago){0,1}$", 1 TSRMLS_CC) == FAILURE &&
|
|
|
|
php_pgsql_convert_match(Z_STRVAL_PP(val), "^@[ \\t]+[+-]{0,1}[ \\t]+(second|seconds|minute|minute|hour|hour|day|days|week|weeks|month|monthes|year|years|decade|decades|century|centuries|millennium|millenniums){1,1}[ \\t]+)+([ \\t]+ago$", 1 TSRMLS_CC) == FAILURE) {
|
2002-04-08 09:37:38 +08:00
|
|
|
err = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
|
|
|
|
php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_NULL:
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
err = 1;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
PGSQL_CONV_CHECK_IGNORE();
|
2002-04-08 09:37:38 +08:00
|
|
|
if (err) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects string or null for PostgreSQL %s field (%s)", Z_STRVAL_PP(type), field);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
#ifdef HAVE_PQESCAPE
|
|
|
|
case PG_BYTEA:
|
|
|
|
switch (Z_TYPE_PP(val)) {
|
|
|
|
case IS_STRING:
|
|
|
|
if (Z_STRLEN_PP(val) == 0) {
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
unsigned char *tmp;
|
|
|
|
size_t to_len;
|
|
|
|
tmp = PQescapeBytea(Z_STRVAL_PP(val), Z_STRLEN_PP(val), &to_len);
|
|
|
|
Z_TYPE_P(new_val) = IS_STRING;
|
|
|
|
Z_STRLEN_P(new_val) = to_len-1; /* PQescapeBytea's to_len includes additional '\0' */
|
|
|
|
Z_STRVAL_P(new_val) = emalloc(to_len);
|
|
|
|
memcpy(Z_STRVAL_P(new_val), tmp, to_len);
|
|
|
|
free(tmp);
|
|
|
|
php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
|
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_LONG:
|
|
|
|
ZVAL_LONG(new_val, Z_LVAL_PP(val));
|
|
|
|
convert_to_string_ex(&new_val);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_DOUBLE:
|
|
|
|
ZVAL_DOUBLE(new_val, Z_DVAL_PP(val));
|
|
|
|
convert_to_string_ex(&new_val);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_NULL:
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
err = 1;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
PGSQL_CONV_CHECK_IGNORE();
|
2002-04-08 09:37:38 +08:00
|
|
|
if (err) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects string, null, long or double value for PostgreSQL '%s' (%s)", Z_STRVAL_PP(type), field);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
case PG_MACADDR:
|
|
|
|
switch(Z_TYPE_PP(val)) {
|
|
|
|
case IS_STRING:
|
|
|
|
if (Z_STRLEN_PP(val) == 0) {
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
}
|
|
|
|
else {
|
2002-04-19 20:24:14 +08:00
|
|
|
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) {
|
2002-04-08 09:37:38 +08:00
|
|
|
err = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
|
|
|
|
php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_NULL:
|
|
|
|
ZVAL_STRING(new_val, "NULL", 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
err = 1;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
PGSQL_CONV_CHECK_IGNORE();
|
2002-04-08 09:37:38 +08:00
|
|
|
if (err) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects string or null for PostgreSQL %s field (%s)", Z_STRVAL_PP(type), field);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* bit */
|
|
|
|
case PG_BIT:
|
|
|
|
case PG_VARBIT:
|
2002-04-21 18:37:40 +08:00
|
|
|
/* geometric */
|
2002-04-08 09:37:38 +08:00
|
|
|
case PG_LINE:
|
|
|
|
case PG_LSEG:
|
|
|
|
case PG_POINT:
|
|
|
|
case PG_BOX:
|
|
|
|
case PG_PATH:
|
|
|
|
case PG_POLYGON:
|
|
|
|
case PG_CIRCLE:
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "does not support PostgreSQL '%s' type (%s)", Z_STRVAL_PP(type), field);
|
2002-04-08 09:37:38 +08:00
|
|
|
err = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PG_UNKNOWN:
|
|
|
|
default:
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "unknown or system data type '%s' for '%s'", Z_STRVAL_PP(type), field);
|
2002-04-08 09:37:38 +08:00
|
|
|
err = 1;
|
|
|
|
break;
|
|
|
|
} /* switch */
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
zval_dtor(new_val);
|
|
|
|
FREE_ZVAL(new_val);
|
|
|
|
break;
|
|
|
|
}
|
2002-04-19 20:24:14 +08:00
|
|
|
if (!skip_field) {
|
|
|
|
/* If field is NULL and HAS DEFAULT, should be skipped */
|
|
|
|
field = php_addslashes(field, strlen(field), &new_len, 0 TSRMLS_CC);
|
|
|
|
add_assoc_zval(result, field, new_val);
|
|
|
|
efree(field);
|
|
|
|
}
|
2002-04-08 09:37:38 +08:00
|
|
|
} /* for */
|
|
|
|
zval_dtor(meta);
|
|
|
|
FREE_ZVAL(meta);
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
/* shouldn't destroy & free zval here */
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
|
2002-04-23 11:42:26 +08:00
|
|
|
/* {{{ proto array pg_convert(resource db, string table, array values[, int options])
|
2002-04-08 09:37:38 +08:00
|
|
|
Check and convert values for PostgreSQL SQL statement */
|
|
|
|
PHP_FUNCTION(pg_convert)
|
|
|
|
{
|
|
|
|
zval *pgsql_link, *values;
|
|
|
|
char *table_name;
|
|
|
|
size_t table_name_len;
|
2002-04-23 11:42:26 +08:00
|
|
|
ulong option = 0;
|
2002-04-08 09:37:38 +08:00
|
|
|
PGconn *pg_link;
|
|
|
|
int id = -1;
|
|
|
|
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
|
2002-04-23 11:42:26 +08:00
|
|
|
"rsa|l", &pgsql_link, &table_name, &table_name_len, &values, &option) == FAILURE) {
|
2002-04-08 09:37:38 +08:00
|
|
|
return;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
if (option & ~PGSQL_CONV_OPTS) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is spedified");
|
2002-04-23 11:42:26 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2002-04-08 09:37:38 +08:00
|
|
|
if (!table_name_len) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Table name is invalid");
|
2002-04-08 09:37:38 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
|
|
|
if (php_pgsql_flush_query(pg_link TSRMLS_CC)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected unhandled result(s) in connection");
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
array_init(return_value);
|
2002-04-23 11:42:26 +08:00
|
|
|
if (php_pgsql_convert(pg_link, table_name, values, return_value, option TSRMLS_CC) == FAILURE) {
|
2002-04-08 09:37:38 +08:00
|
|
|
zval_dtor(return_value);
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-04-23 11:42:26 +08:00
|
|
|
static int do_exec(smart_str *querystr, int expect, PGconn *pg_link, ulong opt TSRMLS_DC)
|
2002-04-21 17:46:29 +08:00
|
|
|
{
|
2002-04-23 11:42:26 +08:00
|
|
|
if (opt & PGSQL_DML_ASYNC) {
|
2002-04-21 17:46:29 +08:00
|
|
|
if (PQsendQuery(pg_link, querystr->c)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
PGresult *pg_result;
|
|
|
|
|
|
|
|
pg_result = PQexec(pg_link, querystr->c);
|
|
|
|
if (PQresultStatus(pg_result) == expect) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Failed to execute '%s'", querystr->c);
|
2002-04-21 17:46:29 +08:00
|
|
|
PQclear(pg_result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2002-04-08 09:37:38 +08:00
|
|
|
/* {{{ php_pgsql_insert
|
|
|
|
*/
|
2002-04-23 11:42:26 +08:00
|
|
|
PHPAPI int php_pgsql_insert(PGconn *pg_link, const char *table, zval *var_array, ulong opt, char **sql TSRMLS_DC)
|
2002-04-08 09:37:38 +08:00
|
|
|
{
|
2002-04-08 10:01:45 +08:00
|
|
|
zval **val, *converted = NULL;
|
2002-04-21 17:46:29 +08:00
|
|
|
char buf[256];
|
|
|
|
char *fld;
|
|
|
|
smart_str querystr = {0};
|
|
|
|
int key_type, fld_len, ret = FAILURE;
|
2002-04-08 09:37:38 +08:00
|
|
|
ulong num_idx;
|
|
|
|
HashPosition pos;
|
|
|
|
|
|
|
|
assert(pg_link != NULL);
|
|
|
|
assert(table != NULL);
|
|
|
|
assert(Z_TYPE_P(var_array) == IS_ARRAY);
|
|
|
|
|
2002-04-21 18:44:31 +08:00
|
|
|
if (zend_hash_num_elements(Z_ARRVAL_P(var_array)) == 0) {
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
2002-04-08 09:37:38 +08:00
|
|
|
/* convert input array if needed */
|
2002-04-23 11:42:26 +08:00
|
|
|
if (!(opt & PGSQL_DML_NO_CONV)) {
|
2002-04-08 09:37:38 +08:00
|
|
|
MAKE_STD_ZVAL(converted);
|
|
|
|
array_init(converted);
|
2002-04-23 11:42:26 +08:00
|
|
|
if (php_pgsql_convert(pg_link, table, var_array, converted, (opt & PGSQL_CONV_OPTS) TSRMLS_CC) == FAILURE) {
|
2002-04-21 17:46:29 +08:00
|
|
|
goto cleanup;
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
var_array = converted;
|
|
|
|
}
|
2002-04-21 17:46:29 +08:00
|
|
|
|
|
|
|
smart_str_appends(&querystr, "INSERT INTO ");
|
|
|
|
smart_str_appends(&querystr, table);
|
|
|
|
smart_str_appends(&querystr, " (");
|
|
|
|
|
|
|
|
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(var_array), &pos);
|
|
|
|
while ((key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(var_array), &fld,
|
|
|
|
&fld_len, &num_idx, 0, &pos)) != HASH_KEY_NON_EXISTANT) {
|
2002-04-08 09:37:38 +08:00
|
|
|
if (key_type == HASH_KEY_IS_LONG) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Expects associative array for values to be inserted");
|
2002-04-21 17:46:29 +08:00
|
|
|
goto cleanup;
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
2002-04-22 16:18:19 +08:00
|
|
|
smart_str_appendl(&querystr, fld, fld_len - 1);
|
|
|
|
smart_str_appendc(&querystr, ',');
|
2002-04-21 17:46:29 +08:00
|
|
|
zend_hash_move_forward_ex(Z_ARRVAL_P(var_array), &pos);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
2002-04-22 16:18:19 +08:00
|
|
|
querystr.len--;
|
2002-04-21 17:46:29 +08:00
|
|
|
smart_str_appends(&querystr, ") VALUES (");
|
2002-04-08 09:37:38 +08:00
|
|
|
|
2002-04-21 17:46:29 +08:00
|
|
|
/* make values string */
|
2002-04-08 09:37:38 +08:00
|
|
|
for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(var_array), &pos);
|
|
|
|
zend_hash_get_current_data_ex(Z_ARRVAL_P(var_array), (void **)&val, &pos) == SUCCESS;
|
|
|
|
zend_hash_move_forward_ex(Z_ARRVAL_P(var_array), &pos)) {
|
2002-04-21 17:46:29 +08:00
|
|
|
|
|
|
|
/* we can avoid the key_type check here, because we tested it in the other loop */
|
2002-04-08 09:37:38 +08:00
|
|
|
switch(Z_TYPE_PP(val)) {
|
|
|
|
case IS_STRING:
|
2002-04-21 17:46:29 +08:00
|
|
|
smart_str_appendl(&querystr, Z_STRVAL_PP(val), Z_STRLEN_PP(val));
|
2002-04-08 09:37:38 +08:00
|
|
|
break;
|
|
|
|
case IS_LONG:
|
2002-04-21 17:46:29 +08:00
|
|
|
smart_str_append_long(&querystr, Z_LVAL_PP(val));
|
2002-04-08 09:37:38 +08:00
|
|
|
break;
|
|
|
|
case IS_DOUBLE:
|
2002-04-21 17:46:29 +08:00
|
|
|
smart_str_appendl(&querystr, buf, sprintf(buf, "%f", Z_DVAL_PP(val)));
|
2002-04-08 09:37:38 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* should not happen */
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Report this error to php-dev@lists.php.net. Type = %d", Z_TYPE_PP(val));
|
2002-04-21 17:46:29 +08:00
|
|
|
goto cleanup;
|
2002-04-08 09:37:38 +08:00
|
|
|
break;
|
|
|
|
}
|
2002-04-21 17:46:29 +08:00
|
|
|
smart_str_appendc(&querystr, ',');
|
|
|
|
}
|
|
|
|
/* Remove the trailing "," */
|
|
|
|
querystr.len--;
|
|
|
|
smart_str_appends(&querystr, ");");
|
|
|
|
smart_str_0(&querystr);
|
|
|
|
|
2002-04-23 11:42:26 +08:00
|
|
|
if ((opt & (PGSQL_DML_EXEC|PGSQL_DML_ASYNC)) &&
|
|
|
|
do_exec(&querystr, PGRES_COMMAND_OK, pg_link, (opt & PGSQL_CONV_OPTS) TSRMLS_CC) == 0) {
|
2002-04-21 17:46:29 +08:00
|
|
|
ret = SUCCESS;
|
2002-04-23 11:42:26 +08:00
|
|
|
}
|
|
|
|
else if (opt & PGSQL_DML_STRING) {
|
|
|
|
ret = SUCCESS;
|
|
|
|
}
|
|
|
|
|
2002-04-21 17:46:29 +08:00
|
|
|
cleanup:
|
2002-04-23 11:42:26 +08:00
|
|
|
if (!(opt & PGSQL_DML_NO_CONV)) {
|
2002-04-08 09:37:38 +08:00
|
|
|
zval_dtor(converted);
|
|
|
|
FREE_ZVAL(converted);
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
if (ret == SUCCESS && (opt & PGSQL_DML_STRING)) {
|
|
|
|
*sql = querystr.c;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
smart_str_free(&querystr);
|
|
|
|
}
|
2002-04-08 09:37:38 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-04-23 11:42:26 +08:00
|
|
|
/* {{{ proto bool pg_insert(resource db, string table, array values[, int options])
|
2002-04-08 09:37:38 +08:00
|
|
|
Insert values (filed=>value) to table */
|
|
|
|
PHP_FUNCTION(pg_insert)
|
|
|
|
{
|
|
|
|
zval *pgsql_link, *values;
|
2002-04-23 11:42:26 +08:00
|
|
|
char *table, *sql = NULL;
|
2002-04-08 09:37:38 +08:00
|
|
|
ulong table_len;
|
2002-04-23 11:42:26 +08:00
|
|
|
ulong option = PGSQL_DML_EXEC;
|
2002-04-08 09:37:38 +08:00
|
|
|
PGconn *pg_link;
|
|
|
|
int id = -1, argc = ZEND_NUM_ARGS();
|
|
|
|
|
2002-04-23 11:42:26 +08:00
|
|
|
if (zend_parse_parameters(argc TSRMLS_CC, "rsa|l",
|
|
|
|
&pgsql_link, &table, &table_len, &values, &option) == FAILURE) {
|
2002-04-08 09:37:38 +08:00
|
|
|
return;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
if (option & ~(PGSQL_CONV_OPTS|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_ASYNC|PGSQL_DML_STRING)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is spedified");
|
2002-04-23 11:42:26 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2002-04-08 09:37:38 +08:00
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
|
|
|
if (php_pgsql_flush_query(pg_link TSRMLS_CC)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected unhandled result(s) in connection");
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
if (php_pgsql_insert(pg_link, table, values, option, &sql TSRMLS_CC) == FAILURE) {
|
2002-04-08 09:37:38 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
if (option & PGSQL_DML_STRING) {
|
|
|
|
RETURN_STRING(sql, 0);
|
|
|
|
}
|
2002-04-08 09:37:38 +08:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
2002-04-21 17:46:29 +08:00
|
|
|
|
|
|
|
static inline int build_assignment_string(smart_str *querystr, HashTable *ht, const char *pad, int pad_len TSRMLS_DC)
|
|
|
|
{
|
|
|
|
HashPosition pos;
|
|
|
|
size_t fld_len;
|
|
|
|
int key_type;
|
|
|
|
ulong num_idx;
|
|
|
|
char *fld;
|
|
|
|
char buf[256];
|
|
|
|
zval **val;
|
|
|
|
|
|
|
|
for (zend_hash_internal_pointer_reset_ex(ht, &pos);
|
|
|
|
zend_hash_get_current_data_ex(ht, (void **)&val, &pos) == SUCCESS;
|
|
|
|
zend_hash_move_forward_ex(ht, &pos)) {
|
|
|
|
key_type = zend_hash_get_current_key_ex(ht, &fld, &fld_len, &num_idx, 0, &pos);
|
|
|
|
if (key_type == HASH_KEY_IS_LONG) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Expects associative array for values to be inserted");
|
2002-04-21 17:46:29 +08:00
|
|
|
return -1;
|
|
|
|
}
|
2002-04-22 16:18:19 +08:00
|
|
|
smart_str_appendl(querystr, fld, fld_len - 1);
|
2002-04-21 17:46:29 +08:00
|
|
|
smart_str_appendc(querystr, '=');
|
|
|
|
|
|
|
|
switch(Z_TYPE_PP(val)) {
|
|
|
|
case IS_STRING:
|
|
|
|
smart_str_appendl(querystr, Z_STRVAL_PP(val), Z_STRLEN_PP(val));
|
|
|
|
break;
|
|
|
|
case IS_LONG:
|
|
|
|
smart_str_append_long(querystr, Z_LVAL_PP(val));
|
|
|
|
break;
|
|
|
|
case IS_DOUBLE:
|
|
|
|
smart_str_appendl(querystr, buf, sprintf(buf, "%f", Z_DVAL_PP(val)));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* should not happen */
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects scaler values other than null. Need to convert?");
|
2002-04-21 17:46:29 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
smart_str_appendl(querystr, pad, pad_len);
|
|
|
|
}
|
|
|
|
querystr->len -= pad_len;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-04-08 09:37:38 +08:00
|
|
|
/* {{{ php_pgsql_update
|
|
|
|
*/
|
2002-04-23 11:42:26 +08:00
|
|
|
PHPAPI int php_pgsql_update(PGconn *pg_link, const char *table, zval *var_array, zval *ids_array, ulong opt, char **sql TSRMLS_DC)
|
2002-04-08 09:37:38 +08:00
|
|
|
{
|
2002-04-21 17:46:29 +08:00
|
|
|
zval *var_converted = NULL, *ids_converted = NULL;
|
|
|
|
smart_str querystr = {0};
|
2002-04-21 18:28:01 +08:00
|
|
|
int ret = FAILURE;
|
2002-04-08 09:37:38 +08:00
|
|
|
|
|
|
|
assert(pg_link != NULL);
|
|
|
|
assert(table != NULL);
|
|
|
|
assert(Z_TYPE_P(var_array) == IS_ARRAY);
|
|
|
|
assert(Z_TYPE_P(ids_array) == IS_ARRAY);
|
2002-04-23 11:42:26 +08:00
|
|
|
assert(!(opt & ~(PGSQL_CONV_OPTS|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_STRING)));
|
2002-04-08 09:37:38 +08:00
|
|
|
|
2002-04-21 18:44:31 +08:00
|
|
|
if (zend_hash_num_elements(Z_ARRVAL_P(var_array)) == 0
|
|
|
|
|| zend_hash_num_elements(Z_ARRVAL_P(ids_array)) == 0) {
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
2002-04-23 11:42:26 +08:00
|
|
|
if (!(opt & PGSQL_DML_NO_CONV)) {
|
2002-04-08 09:37:38 +08:00
|
|
|
MAKE_STD_ZVAL(var_converted);
|
|
|
|
array_init(var_converted);
|
2002-04-23 11:42:26 +08:00
|
|
|
if (php_pgsql_convert(pg_link, table, var_array, var_converted, (opt & PGSQL_CONV_OPTS) TSRMLS_CC) == FAILURE) {
|
2002-04-21 17:46:29 +08:00
|
|
|
goto cleanup;
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
var_array = var_converted;
|
|
|
|
MAKE_STD_ZVAL(ids_converted);
|
|
|
|
array_init(ids_converted);
|
2002-04-23 11:42:26 +08:00
|
|
|
if (php_pgsql_convert(pg_link, table, ids_array, ids_converted, (opt & PGSQL_CONV_OPTS) TSRMLS_CC) == FAILURE) {
|
2002-04-21 17:46:29 +08:00
|
|
|
goto cleanup;
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
ids_array = ids_converted;
|
|
|
|
}
|
|
|
|
|
2002-04-21 17:46:29 +08:00
|
|
|
smart_str_appends(&querystr, "UPDATE ");
|
|
|
|
smart_str_appends(&querystr, table);
|
|
|
|
smart_str_appends(&querystr, " SET ");
|
2002-04-08 09:37:38 +08:00
|
|
|
|
2002-04-21 17:46:29 +08:00
|
|
|
if (build_assignment_string(&querystr, Z_ARRVAL_P(var_array), ",", 1 TSRMLS_CC))
|
|
|
|
goto cleanup;
|
2002-04-08 09:37:38 +08:00
|
|
|
|
2002-04-21 17:46:29 +08:00
|
|
|
smart_str_appends(&querystr, " WHERE ");
|
|
|
|
|
|
|
|
if (build_assignment_string(&querystr, Z_ARRVAL_P(ids_array), " AND ", sizeof(" AND ")-1 TSRMLS_CC))
|
|
|
|
goto cleanup;
|
2002-04-08 09:37:38 +08:00
|
|
|
|
2002-04-21 17:46:29 +08:00
|
|
|
smart_str_appendc(&querystr, ';');
|
|
|
|
smart_str_0(&querystr);
|
2002-04-08 09:37:38 +08:00
|
|
|
|
2002-04-23 11:42:26 +08:00
|
|
|
if (do_exec(&querystr, PGRES_COMMAND_OK, pg_link, opt TSRMLS_CC) == 0)
|
2002-04-21 17:46:29 +08:00
|
|
|
ret = SUCCESS;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (var_converted) {
|
|
|
|
zval_dtor(var_converted);
|
|
|
|
FREE_ZVAL(var_converted);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
2002-04-21 17:46:29 +08:00
|
|
|
if (ids_converted) {
|
|
|
|
zval_dtor(ids_converted);
|
|
|
|
FREE_ZVAL(ids_converted);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
if (ret == SUCCESS && (opt & PGSQL_DML_STRING)) {
|
|
|
|
*sql = querystr.c;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
smart_str_free(&querystr);
|
|
|
|
}
|
2002-04-08 09:37:38 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-04-23 11:42:26 +08:00
|
|
|
/* {{{ proto bool pg_update(resource db, string table, array fields, array ids[, int options])
|
2002-04-08 09:37:38 +08:00
|
|
|
Update table using values (field=>value) and ids (id=>value) */
|
|
|
|
PHP_FUNCTION(pg_update)
|
|
|
|
{
|
|
|
|
zval *pgsql_link, *values, *ids;
|
2002-04-23 11:42:26 +08:00
|
|
|
char *table, *sql = NULL;
|
2002-04-08 09:37:38 +08:00
|
|
|
ulong table_len;
|
2002-04-23 11:42:26 +08:00
|
|
|
ulong option = PGSQL_DML_EXEC;
|
2002-04-08 09:37:38 +08:00
|
|
|
PGconn *pg_link;
|
|
|
|
int id = -1, argc = ZEND_NUM_ARGS();
|
|
|
|
|
2002-04-23 11:42:26 +08:00
|
|
|
if (zend_parse_parameters(argc TSRMLS_CC, "rsaa|l",
|
|
|
|
&pgsql_link, &table, &table_len, &values, &ids, &option) == FAILURE) {
|
2002-04-08 09:37:38 +08:00
|
|
|
return;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
if (option & ~(PGSQL_CONV_OPTS|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_STRING)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is spedified");
|
2002-04-23 11:42:26 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2002-04-08 09:37:38 +08:00
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
|
|
|
if (php_pgsql_flush_query(pg_link TSRMLS_CC)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected unhandled result(s) in connection");
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
if (php_pgsql_update(pg_link, table, values, ids, option, &sql TSRMLS_CC) == FAILURE) {
|
2002-04-08 09:37:38 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
if (option & PGSQL_DML_STRING) {
|
|
|
|
RETURN_STRING(sql, 0);
|
|
|
|
}
|
2002-04-08 09:37:38 +08:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ php_pgsql_delete
|
|
|
|
*/
|
2002-04-23 11:42:26 +08:00
|
|
|
PHPAPI int php_pgsql_delete(PGconn *pg_link, const char *table, zval *ids_array, ulong opt, char **sql TSRMLS_DC)
|
2002-04-08 09:37:38 +08:00
|
|
|
{
|
2002-04-21 17:46:29 +08:00
|
|
|
zval *ids_converted = NULL;
|
|
|
|
smart_str querystr = {0};
|
|
|
|
int ret = FAILURE;
|
2002-04-08 09:37:38 +08:00
|
|
|
|
|
|
|
assert(pg_link != NULL);
|
|
|
|
assert(table != NULL);
|
|
|
|
assert(Z_TYPE_P(ids_array) == IS_ARRAY);
|
2002-04-23 11:42:26 +08:00
|
|
|
assert(!(opt & ~(PGSQL_CONV_FORCE_NULL|PGSQL_DML_EXEC|PGSQL_DML_STRING)));
|
|
|
|
|
2002-04-21 18:44:31 +08:00
|
|
|
if (zend_hash_num_elements(Z_ARRVAL_P(ids_array)) == 0) {
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
2002-04-23 11:42:26 +08:00
|
|
|
if (!(opt & PGSQL_DML_NO_CONV)) {
|
2002-04-08 09:37:38 +08:00
|
|
|
MAKE_STD_ZVAL(ids_converted);
|
|
|
|
array_init(ids_converted);
|
2002-04-23 11:42:26 +08:00
|
|
|
if (php_pgsql_convert(pg_link, table, ids_array, ids_converted, (opt & PGSQL_CONV_OPTS) TSRMLS_CC) == FAILURE) {
|
2002-04-21 17:46:29 +08:00
|
|
|
goto cleanup;
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
ids_array = ids_converted;
|
|
|
|
}
|
|
|
|
|
2002-04-21 17:46:29 +08:00
|
|
|
smart_str_appends(&querystr, "DELETE FROM ");
|
|
|
|
smart_str_appends(&querystr, table);
|
|
|
|
smart_str_appends(&querystr, " WHERE ");
|
2002-04-08 09:37:38 +08:00
|
|
|
|
2002-04-21 17:46:29 +08:00
|
|
|
if (build_assignment_string(&querystr, Z_ARRVAL_P(ids_array), " AND ", sizeof(" AND ")-1 TSRMLS_CC))
|
|
|
|
goto cleanup;
|
|
|
|
|
2002-04-21 18:22:31 +08:00
|
|
|
smart_str_appendc(&querystr, ';');
|
|
|
|
smart_str_0(&querystr);
|
2002-04-21 17:46:29 +08:00
|
|
|
|
2002-04-23 11:42:26 +08:00
|
|
|
if (do_exec(&querystr, PGRES_COMMAND_OK, pg_link, opt TSRMLS_CC) == 0)
|
2002-04-21 17:46:29 +08:00
|
|
|
ret = SUCCESS;
|
|
|
|
|
|
|
|
cleanup:
|
2002-04-23 11:42:26 +08:00
|
|
|
if (!(opt & PGSQL_DML_NO_CONV)) {
|
2002-04-08 09:37:38 +08:00
|
|
|
zval_dtor(ids_converted);
|
|
|
|
FREE_ZVAL(ids_converted);
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
if (ret == SUCCESS && (opt & PGSQL_DML_STRING)) {
|
|
|
|
*sql = estrdup(querystr.c);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
smart_str_free(&querystr);
|
|
|
|
}
|
2002-04-08 09:37:38 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-04-23 11:42:26 +08:00
|
|
|
/* {{{ proto bool pg_delete(resource db, string table, array ids[, int options])
|
2002-04-08 09:37:38 +08:00
|
|
|
Delete records has ids (id=>value) */
|
|
|
|
PHP_FUNCTION(pg_delete)
|
|
|
|
{
|
|
|
|
zval *pgsql_link, *ids;
|
2002-04-23 11:42:26 +08:00
|
|
|
char *table, *sql = NULL;
|
|
|
|
ulong table_len, option = PGSQL_DML_EXEC;
|
2002-04-08 09:37:38 +08:00
|
|
|
PGconn *pg_link;
|
|
|
|
int id = -1, argc = ZEND_NUM_ARGS();
|
|
|
|
|
2002-04-23 11:42:26 +08:00
|
|
|
if (zend_parse_parameters(argc TSRMLS_CC, "rsa|l",
|
|
|
|
&pgsql_link, &table, &table_len, &ids, &option) == FAILURE) {
|
2002-04-08 09:37:38 +08:00
|
|
|
return;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
if (option & ~(PGSQL_CONV_FORCE_NULL|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_STRING)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is spedified");
|
2002-04-23 11:42:26 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2002-04-08 09:37:38 +08:00
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
|
|
|
if (php_pgsql_flush_query(pg_link TSRMLS_CC)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected unhandled result(s) in connection");
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
if (php_pgsql_delete(pg_link, table, ids, option, &sql TSRMLS_CC) == FAILURE) {
|
2002-04-08 09:37:38 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
if (option & PGSQL_DML_STRING) {
|
|
|
|
RETURN_STRING(sql, 0);
|
|
|
|
}
|
2002-04-08 09:37:38 +08:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ php_pgsql_result2array
|
|
|
|
*/
|
2002-04-08 10:01:45 +08:00
|
|
|
PHPAPI int php_pgsql_result2array(PGresult *pg_result, zval *ret_array TSRMLS_DC)
|
2002-04-08 09:37:38 +08:00
|
|
|
{
|
|
|
|
zval *row;
|
|
|
|
char *field_name, *element, *data;
|
|
|
|
size_t num_fields, element_len, data_len;
|
2002-04-20 10:31:48 +08:00
|
|
|
int pg_numrows, pg_row;
|
|
|
|
uint i;
|
2002-04-08 09:37:38 +08:00
|
|
|
assert(Z_TYPE_P(ret_array) == IS_ARRAY);
|
|
|
|
|
|
|
|
if ((pg_numrows = PQntuples(pg_result)) <= 0) {
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
for (pg_row = 0; pg_row < pg_numrows; pg_row++) {
|
|
|
|
MAKE_STD_ZVAL(row);
|
|
|
|
array_init(row);
|
|
|
|
add_index_zval(ret_array, pg_row, row);
|
|
|
|
for (i = 0, num_fields = PQnfields(pg_result); i < num_fields; i++) {
|
|
|
|
if (PQgetisnull(pg_result, pg_row, i)) {
|
|
|
|
field_name = PQfname(pg_result, i);
|
|
|
|
add_assoc_null(row, field_name);
|
|
|
|
} else {
|
|
|
|
element = PQgetvalue(pg_result, pg_row, i);
|
|
|
|
element_len = (element ? strlen(element) : 0);
|
|
|
|
if (element) {
|
|
|
|
if (PG(magic_quotes_runtime)) {
|
|
|
|
data = php_addslashes(element, element_len, &data_len, 0 TSRMLS_CC);
|
|
|
|
} else {
|
|
|
|
data = safe_estrndup(element, element_len);
|
|
|
|
data_len = element_len;
|
|
|
|
}
|
|
|
|
field_name = PQfname(pg_result, i);
|
|
|
|
add_assoc_stringl(row, field_name, data, data_len, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ php_pgsql_select
|
|
|
|
*/
|
2002-04-23 11:42:26 +08:00
|
|
|
PHPAPI int php_pgsql_select(PGconn *pg_link, const char *table, zval *ids_array, zval *ret_array, ulong opt, char **sql TSRMLS_DC)
|
2002-04-08 09:37:38 +08:00
|
|
|
{
|
2002-04-21 17:46:29 +08:00
|
|
|
zval *ids_converted = NULL;
|
|
|
|
smart_str querystr = {0};
|
|
|
|
int ret = FAILURE;
|
2002-04-08 09:37:38 +08:00
|
|
|
PGresult *pg_result;
|
|
|
|
|
|
|
|
assert(pg_link != NULL);
|
|
|
|
assert(table != NULL);
|
|
|
|
assert(Z_TYPE_P(ids_array) == IS_ARRAY);
|
|
|
|
assert(Z_TYPE_P(ret_array) == IS_ARRAY);
|
2002-04-23 11:42:26 +08:00
|
|
|
assert(!(opt & ~(PGSQL_CONV_OPTS|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_ASYNC|PGSQL_DML_STRING)));
|
|
|
|
|
2002-04-21 18:44:31 +08:00
|
|
|
if (zend_hash_num_elements(Z_ARRVAL_P(ids_array)) == 0) {
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
2002-04-23 11:42:26 +08:00
|
|
|
if (!(opt & PGSQL_DML_NO_CONV)) {
|
2002-04-08 09:37:38 +08:00
|
|
|
MAKE_STD_ZVAL(ids_converted);
|
|
|
|
array_init(ids_converted);
|
2002-04-23 11:42:26 +08:00
|
|
|
if (php_pgsql_convert(pg_link, table, ids_array, ids_converted, (opt & PGSQL_CONV_OPTS) TSRMLS_CC) == FAILURE) {
|
2002-04-21 17:46:29 +08:00
|
|
|
goto cleanup;
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
ids_array = ids_converted;
|
|
|
|
}
|
|
|
|
|
2002-04-21 17:46:29 +08:00
|
|
|
smart_str_appends(&querystr, "SELECT * FROM ");
|
|
|
|
smart_str_appends(&querystr, table);
|
|
|
|
smart_str_appends(&querystr, " WHERE ");
|
2002-04-08 09:37:38 +08:00
|
|
|
|
2002-04-21 17:46:29 +08:00
|
|
|
if (build_assignment_string(&querystr, Z_ARRVAL_P(ids_array), " AND ", sizeof(" AND ")-1 TSRMLS_CC))
|
|
|
|
goto cleanup;
|
2002-04-08 09:37:38 +08:00
|
|
|
|
2002-04-21 17:46:29 +08:00
|
|
|
smart_str_appendc(&querystr, ';');
|
2002-04-21 18:22:31 +08:00
|
|
|
smart_str_0(&querystr);
|
2002-04-21 17:46:29 +08:00
|
|
|
|
|
|
|
pg_result = PQexec(pg_link, querystr.c);
|
|
|
|
if (PQresultStatus(pg_result) == PGRES_TUPLES_OK) {
|
|
|
|
ret = php_pgsql_result2array(pg_result, ret_array TSRMLS_CC);
|
|
|
|
} else {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Failed to execute '%s'", querystr.c);
|
2002-04-08 09:37:38 +08:00
|
|
|
PQclear(pg_result);
|
|
|
|
}
|
|
|
|
|
2002-04-21 17:46:29 +08:00
|
|
|
cleanup:
|
2002-04-23 11:42:26 +08:00
|
|
|
if (!(opt & PGSQL_DML_NO_CONV)) {
|
2002-04-21 17:46:29 +08:00
|
|
|
zval_dtor(ids_converted);
|
|
|
|
FREE_ZVAL(ids_converted);
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
if (ret == SUCCESS && (opt & PGSQL_DML_STRING)) {
|
|
|
|
*sql = querystr.c;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
smart_str_free(&querystr);
|
|
|
|
}
|
2002-04-08 09:37:38 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-04-23 11:42:26 +08:00
|
|
|
/* {{{ proto array pg_select(resource db, string table, array ids[, int options])
|
2002-04-08 09:37:38 +08:00
|
|
|
Select records that has ids (id=>value) */
|
|
|
|
PHP_FUNCTION(pg_select)
|
|
|
|
{
|
|
|
|
zval *pgsql_link, *ids;
|
2002-04-23 11:42:26 +08:00
|
|
|
char *table, *sql = NULL;
|
|
|
|
ulong table_len, option = PGSQL_DML_EXEC;
|
2002-04-08 09:37:38 +08:00
|
|
|
PGconn *pg_link;
|
|
|
|
int id = -1, argc = ZEND_NUM_ARGS();
|
|
|
|
|
2002-04-23 11:42:26 +08:00
|
|
|
if (zend_parse_parameters(argc TSRMLS_CC, "rsa|l",
|
|
|
|
&pgsql_link, &table, &table_len, &ids, &option) == FAILURE) {
|
2002-04-08 09:37:38 +08:00
|
|
|
return;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
if (option & ~(PGSQL_CONV_FORCE_NULL|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_ASYNC|PGSQL_DML_STRING)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is spedified");
|
2002-04-23 11:42:26 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2002-04-08 09:37:38 +08:00
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
|
|
|
|
|
|
|
if (php_pgsql_flush_query(pg_link TSRMLS_CC)) {
|
2002-09-05 06:25:13 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected unhandled result(s) in connection");
|
2002-04-08 09:37:38 +08:00
|
|
|
}
|
|
|
|
array_init(return_value);
|
2002-04-23 11:42:26 +08:00
|
|
|
if (php_pgsql_select(pg_link, table, ids, return_value, option, &sql TSRMLS_CC) == FAILURE) {
|
2002-04-08 09:37:38 +08:00
|
|
|
zval_dtor(return_value);
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2002-04-23 11:42:26 +08:00
|
|
|
if (option & PGSQL_DML_STRING) {
|
|
|
|
zval_dtor(return_value);
|
|
|
|
RETURN_STRING(sql, 0);
|
|
|
|
}
|
2002-04-08 09:37:38 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
1999-04-22 10:48:28 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Local variables:
|
|
|
|
* tab-width: 4
|
|
|
|
* c-basic-offset: 4
|
|
|
|
* End:
|
2001-09-09 21:29:31 +08:00
|
|
|
* vim600: sw=4 ts=4 fdm=marker
|
|
|
|
* vim<600: sw=4 ts=4
|
1999-04-22 10:48:28 +08:00
|
|
|
*/
|