2004-05-20 02:27:49 +00:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| PHP Version 5 |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2014-01-03 03:08:10 +00:00
| Copyright ( c ) 1997 - 2014 The PHP Group |
2004-05-20 02:27:49 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-01 12:51:34 +00:00
| This source file is subject to version 3.01 of the PHP license , |
2004-05-20 02:27:49 +00:00
| that is bundled with this package in the file LICENSE , and is |
| available through the world - wide - web at the following url : |
2006-01-01 12:51:34 +00:00
| http : //www.php.net/license/3_01.txt |
2004-05-20 02:27:49 +00: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 . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2005-11-29 02:11:39 +00:00
| Authors : Edin Kadribasic < edink @ emini . dk > |
| Ilia Alshanestsky < ilia @ prohost . org > |
| Wez Furlong < wez @ php . net > |
2004-05-20 02:27:49 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
/* $Id$ */
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include "php.h"
# include "php_ini.h"
# include "ext/standard/info.h"
2013-06-02 12:00:40 +00:00
# include "main/php_network.h"
2004-05-20 02:27:49 +00:00
# include "pdo/php_pdo.h"
# include "pdo/php_pdo_driver.h"
2013-06-04 15:20:20 +00:00
# include "pdo/php_pdo_error.h"
2010-06-10 11:11:29 +00:00
# include "ext/standard/file.h"
2004-05-20 21:50:25 +00:00
2005-12-20 21:10:43 +00:00
# undef PACKAGE_BUGREPORT
# undef PACKAGE_NAME
# undef PACKAGE_STRING
# undef PACKAGE_TARNAME
# undef PACKAGE_VERSION
2004-05-20 21:50:25 +00:00
# include "pg_config.h" /* needed for PG_VERSION */
2004-05-20 02:27:49 +00:00
# include "php_pdo_pgsql.h"
# include "php_pdo_pgsql_int.h"
2004-07-28 00:40:01 +00:00
# include "zend_exceptions.h"
2004-05-20 02:27:49 +00:00
2004-09-23 21:15:51 +00:00
static char * _pdo_pgsql_trim_message ( const char * message , int persistent )
2004-07-28 00:51:48 +00:00
{
register int i = strlen ( message ) - 1 ;
2004-09-23 21:15:51 +00:00
char * tmp ;
2004-07-28 00:51:48 +00:00
if ( i > 1 & & ( message [ i - 1 ] = = ' \r ' | | message [ i - 1 ] = = ' \n ' ) & & message [ i ] = = ' . ' ) {
- - i ;
}
while ( i > 0 & & ( message [ i ] = = ' \r ' | | message [ i ] = = ' \n ' ) ) {
- - i ;
}
+ + i ;
2004-09-23 21:15:51 +00:00
tmp = pemalloc ( i + 1 , persistent ) ;
memcpy ( tmp , message , i ) ;
tmp [ i ] = ' \0 ' ;
2014-03-09 10:43:13 +00:00
2004-09-23 21:15:51 +00:00
return tmp ;
2004-07-28 00:51:48 +00:00
}
2013-06-04 15:20:20 +00:00
int _pdo_pgsql_error ( pdo_dbh_t * dbh , pdo_stmt_t * stmt , int errcode , const char * sqlstate , const char * msg , const char * file , int line TSRMLS_DC ) /* { { { */
2004-05-20 02:27:49 +00:00
{
2004-05-20 17:43:56 +00:00
pdo_pgsql_db_handle * H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
2005-01-07 05:25:57 +00:00
pdo_error_type * pdo_err = stmt ? & stmt - > error_code : & dbh - > error_code ;
2004-05-20 17:43:56 +00:00
pdo_pgsql_error_info * einfo = & H - > einfo ;
char * errmsg = PQerrorMessage ( H - > server ) ;
einfo - > errcode = errcode ;
einfo - > file = file ;
einfo - > line = line ;
if ( einfo - > errmsg ) {
2004-09-23 21:15:51 +00:00
pefree ( einfo - > errmsg , dbh - > is_persistent ) ;
2004-05-20 17:43:56 +00:00
einfo - > errmsg = NULL ;
}
2013-05-31 06:39:32 +00:00
if ( sqlstate = = NULL | | strlen ( sqlstate ) > = sizeof ( pdo_error_type ) ) {
2005-05-13 18:09:03 +00:00
strcpy ( * pdo_err , " HY000 " ) ;
}
else {
strcpy ( * pdo_err , sqlstate ) ;
2004-05-20 17:43:56 +00:00
}
2013-06-04 15:20:20 +00:00
if ( msg ) {
einfo - > errmsg = estrdup ( msg ) ;
}
else if ( errmsg ) {
2004-09-23 21:15:51 +00:00
einfo - > errmsg = _pdo_pgsql_trim_message ( errmsg , dbh - > is_persistent ) ;
2004-05-20 17:43:56 +00:00
}
2004-07-28 00:40:01 +00:00
if ( ! dbh - > methods ) {
2010-01-12 12:46:54 +00:00
zend_throw_exception_ex ( php_pdo_get_exception ( ) , einfo - > errcode TSRMLS_CC , " SQLSTATE[%s] [%d] %s " ,
2005-01-07 05:25:57 +00:00
* pdo_err , einfo - > errcode , einfo - > errmsg ) ;
2004-07-28 00:40:01 +00:00
}
2013-06-04 15:20:20 +00:00
2004-05-20 17:43:56 +00:00
return errcode ;
2004-05-20 02:27:49 +00:00
}
/* }}} */
2005-02-20 19:26:27 +00:00
static void _pdo_pgsql_notice ( pdo_dbh_t * dbh , const char * message ) /* { { { */
{
/* pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; */
}
/* }}} */
2004-05-20 17:43:56 +00:00
static int pdo_pgsql_fetch_error_func ( pdo_dbh_t * dbh , pdo_stmt_t * stmt , zval * info TSRMLS_DC ) /* { { { */
2004-05-20 02:27:49 +00:00
{
2004-05-20 17:43:56 +00:00
pdo_pgsql_db_handle * H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
pdo_pgsql_error_info * einfo = & H - > einfo ;
if ( einfo - > errcode ) {
add_next_index_long ( info , einfo - > errcode ) ;
2014-04-15 11:40:40 +00:00
add_next_index_string ( info , einfo - > errmsg ) ;
2004-05-20 17:43:56 +00:00
}
return 1 ;
2004-05-20 02:27:49 +00:00
}
/* }}} */
2005-11-29 02:11:39 +00:00
/* {{{ pdo_pgsql_create_lob_stream */
static size_t pgsql_lob_write ( php_stream * stream , const char * buf , size_t count TSRMLS_DC )
{
struct pdo_pgsql_lob_self * self = ( struct pdo_pgsql_lob_self * ) stream - > abstract ;
return lo_write ( self - > conn , self - > lfd , ( char * ) buf , count ) ;
}
static size_t pgsql_lob_read ( php_stream * stream , char * buf , size_t count TSRMLS_DC )
{
struct pdo_pgsql_lob_self * self = ( struct pdo_pgsql_lob_self * ) stream - > abstract ;
return lo_read ( self - > conn , self - > lfd , buf , count ) ;
}
static int pgsql_lob_close ( php_stream * stream , int close_handle TSRMLS_DC )
{
struct pdo_pgsql_lob_self * self = ( struct pdo_pgsql_lob_self * ) stream - > abstract ;
pdo_dbh_t * dbh = self - > dbh ;
if ( close_handle ) {
lo_close ( self - > conn , self - > lfd ) ;
}
efree ( self ) ;
2005-12-06 21:44:15 +00:00
php_pdo_dbh_delref ( dbh TSRMLS_CC ) ;
2005-11-29 02:11:39 +00:00
return 0 ;
}
static int pgsql_lob_flush ( php_stream * stream TSRMLS_DC )
{
return 0 ;
}
static int pgsql_lob_seek ( php_stream * stream , off_t offset , int whence ,
off_t * newoffset TSRMLS_DC )
{
struct pdo_pgsql_lob_self * self = ( struct pdo_pgsql_lob_self * ) stream - > abstract ;
int pos = lo_lseek ( self - > conn , self - > lfd , offset , whence ) ;
* newoffset = pos ;
return pos > = 0 ? 0 : - 1 ;
}
php_stream_ops pdo_pgsql_lob_stream_ops = {
pgsql_lob_write ,
pgsql_lob_read ,
pgsql_lob_close ,
pgsql_lob_flush ,
" pdo_pgsql lob stream " ,
pgsql_lob_seek ,
NULL ,
NULL ,
NULL
} ;
php_stream * pdo_pgsql_create_lob_stream ( pdo_dbh_t * dbh , int lfd , Oid oid TSRMLS_DC )
{
php_stream * stm ;
struct pdo_pgsql_lob_self * self = ecalloc ( 1 , sizeof ( * self ) ) ;
pdo_pgsql_db_handle * H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
self - > dbh = dbh ;
self - > lfd = lfd ;
self - > oid = oid ;
self - > conn = H - > server ;
stm = php_stream_alloc ( & pdo_pgsql_lob_stream_ops , self , 0 , " r+b " ) ;
if ( stm ) {
php_pdo_dbh_addref ( dbh TSRMLS_CC ) ;
return stm ;
}
efree ( self ) ;
return NULL ;
}
/* }}} */
2004-05-20 02:27:49 +00:00
static int pgsql_handle_closer ( pdo_dbh_t * dbh TSRMLS_DC ) /* { { { */
{
pdo_pgsql_db_handle * H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
2004-05-25 14:12:15 +00:00
if ( H ) {
if ( H - > server ) {
PQfinish ( H - > server ) ;
H - > server = NULL ;
}
if ( H - > einfo . errmsg ) {
2004-09-23 21:15:51 +00:00
pefree ( H - > einfo . errmsg , dbh - > is_persistent ) ;
2004-05-25 14:12:15 +00:00
H - > einfo . errmsg = NULL ;
}
pefree ( H , dbh - > is_persistent ) ;
2004-07-28 00:40:01 +00:00
dbh - > driver_data = NULL ;
2004-05-20 18:19:03 +00:00
}
2004-05-20 02:27:49 +00:00
return 0 ;
}
/* }}} */
2005-01-21 00:39:03 +00:00
static int pgsql_handle_preparer ( pdo_dbh_t * dbh , const char * sql , long sql_len , pdo_stmt_t * stmt , zval * driver_options TSRMLS_DC )
2004-05-20 02:27:49 +00:00
{
pdo_pgsql_db_handle * H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
pdo_pgsql_stmt * S = ecalloc ( 1 , sizeof ( pdo_pgsql_stmt ) ) ;
2005-01-13 01:59:39 +00:00
int scrollable ;
2005-07-08 15:27:34 +00:00
int ret ;
char * nsql = NULL ;
int nsql_len = 0 ;
2006-04-09 08:17:50 +00:00
int emulate = 0 ;
2014-03-09 13:08:17 +00:00
int execute_only = 0 ;
2004-05-20 02:27:49 +00:00
S - > H = H ;
stmt - > driver_data = S ;
stmt - > methods = & pgsql_stmt_methods ;
2005-01-13 01:59:39 +00:00
scrollable = pdo_attr_lval ( driver_options , PDO_ATTR_CURSOR ,
PDO_CURSOR_FWDONLY TSRMLS_CC ) = = PDO_CURSOR_SCROLL ;
if ( scrollable ) {
2006-05-08 14:33:00 +00:00
if ( S - > cursor_name ) {
efree ( S - > cursor_name ) ;
}
2009-11-04 19:32:27 +00:00
spprintf ( & S - > cursor_name , 0 , " pdo_crsr_%08x " , + + H - > stmt_counter ) ;
2009-03-28 02:58:04 +00:00
emulate = 1 ;
2014-03-09 10:43:13 +00:00
} else if ( driver_options ) {
2014-03-09 11:14:23 +00:00
if ( pdo_attr_lval ( driver_options , PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT , H - > disable_native_prepares TSRMLS_CC ) = = 1 ) {
php_error_docref ( NULL TSRMLS_CC , E_DEPRECATED , " PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT is deprecated, use PDO::ATTR_EMULATE_PREPARES instead " ) ;
emulate = 1 ;
}
if ( pdo_attr_lval ( driver_options , PDO_ATTR_EMULATE_PREPARES , H - > emulate_prepares TSRMLS_CC ) = = 1 ) {
2006-04-09 08:17:50 +00:00
emulate = 1 ;
}
2014-03-09 13:08:17 +00:00
if ( pdo_attr_lval ( driver_options , PDO_PGSQL_ATTR_DISABLE_PREPARES , H - > disable_prepares TSRMLS_CC ) = = 1 ) {
execute_only = 1 ;
}
2009-10-07 17:40:16 +00:00
} else {
emulate = H - > disable_native_prepares | | H - > emulate_prepares ;
2014-03-09 13:08:17 +00:00
execute_only = H - > disable_prepares ;
2006-04-09 08:17:50 +00:00
}
if ( ! emulate & & PQprotocolVersion ( H - > server ) > 2 ) {
2005-07-20 02:37:57 +00:00
stmt - > supports_placeholders = PDO_PLACEHOLDER_NAMED ;
stmt - > named_rewrite_template = " $%d " ;
ret = pdo_parse_params ( stmt , ( char * ) sql , sql_len , & nsql , & nsql_len TSRMLS_CC ) ;
if ( ret = = 1 ) {
/* query was re-written */
sql = nsql ;
} else if ( ret = = - 1 ) {
/* couldn't grok it */
strcpy ( dbh - > error_code , stmt - > error_code ) ;
return 0 ;
}
2005-07-08 15:27:34 +00:00
2014-03-09 13:08:17 +00:00
if ( ! execute_only ) {
/* prepared query: set the query name and defer the
actual prepare until the first execute call */
spprintf ( & S - > stmt_name , 0 , " pdo_stmt_%08x " , + + H - > stmt_counter ) ;
}
2014-03-09 10:43:13 +00:00
2005-07-20 02:37:57 +00:00
if ( nsql ) {
2005-12-01 16:33:01 +00:00
S - > query = nsql ;
2005-11-25 03:35:04 +00:00
} else {
S - > query = estrdup ( sql ) ;
2005-07-20 02:37:57 +00:00
}
2005-11-25 03:35:04 +00:00
return 1 ;
2005-07-08 15:27:34 +00:00
}
stmt - > supports_placeholders = PDO_PLACEHOLDER_NONE ;
2005-02-12 20:55:28 +00:00
return 1 ;
2004-05-20 02:27:49 +00:00
}
2004-05-20 17:43:56 +00:00
static long pgsql_handle_doer ( pdo_dbh_t * dbh , const char * sql , long sql_len TSRMLS_DC )
2004-05-20 02:27:49 +00:00
{
pdo_pgsql_db_handle * H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
2004-05-20 17:43:56 +00:00
PGresult * res ;
2006-01-29 17:35:54 +00:00
long ret = 1 ;
2006-03-13 11:37:51 +00:00
ExecStatusType qs ;
2014-03-09 10:43:13 +00:00
2004-05-20 17:43:56 +00:00
if ( ! ( res = PQexec ( H - > server , sql ) ) ) {
/* fatal error */
2005-05-13 18:09:03 +00:00
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , NULL ) ;
2005-06-28 14:54:44 +00:00
return - 1 ;
2006-01-29 17:35:54 +00:00
}
2006-03-13 11:37:51 +00:00
qs = PQresultStatus ( res ) ;
2006-01-29 17:35:54 +00:00
if ( qs ! = PGRES_COMMAND_OK & & qs ! = PGRES_TUPLES_OK ) {
pdo_pgsql_error ( dbh , qs , pdo_pgsql_sqlstate ( res ) ) ;
2004-05-20 20:04:11 +00:00
PQclear ( res ) ;
2006-01-29 17:35:54 +00:00
return - 1 ;
2004-05-20 17:43:56 +00:00
}
2006-01-29 17:35:54 +00:00
H - > pgoid = PQoidValue ( res ) ;
2012-03-08 08:52:28 +00:00
ret = ( qs = = PGRES_COMMAND_OK ) ? atol ( PQcmdTuples ( res ) ) : 0L ;
2006-01-29 17:35:54 +00:00
PQclear ( res ) ;
2004-05-20 02:27:49 +00:00
2006-01-29 17:35:54 +00:00
return ret ;
2004-05-20 02:27:49 +00:00
}
2005-02-05 22:55:23 +00:00
static int pgsql_handle_quoter ( pdo_dbh_t * dbh , const char * unquoted , int unquotedlen , char * * quoted , int * quotedlen , enum pdo_param_type paramtype TSRMLS_DC )
2004-05-20 02:27:49 +00:00
{
2005-02-06 01:27:27 +00:00
unsigned char * escaped ;
2006-10-06 22:34:16 +00:00
pdo_pgsql_db_handle * H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
2009-04-30 12:38:43 +00:00
size_t tmp_len ;
2014-03-09 10:43:13 +00:00
2005-02-06 01:27:27 +00:00
switch ( paramtype ) {
case PDO_PARAM_LOB :
/* escapedlen returned by PQescapeBytea() accounts for trailing 0 */
2013-08-21 09:08:16 +00:00
escaped = PQescapeByteaConn ( H - > server , ( unsigned char * ) unquoted , ( size_t ) unquotedlen , & tmp_len ) ;
2009-04-30 12:38:43 +00:00
* quotedlen = ( int ) tmp_len + 1 ;
2005-02-06 01:27:27 +00:00
* quoted = emalloc ( * quotedlen + 1 ) ;
memcpy ( ( * quoted ) + 1 , escaped , * quotedlen - 2 ) ;
( * quoted ) [ 0 ] = ' \' ' ;
( * quoted ) [ * quotedlen - 1 ] = ' \' ' ;
( * quoted ) [ * quotedlen ] = ' \0 ' ;
2006-11-29 15:45:59 +00:00
PQfreemem ( escaped ) ;
2005-02-06 01:27:27 +00:00
break ;
2006-10-06 22:34:16 +00:00
default :
2006-10-04 23:53:36 +00:00
* quoted = safe_emalloc ( 2 , unquotedlen , 3 ) ;
2005-02-06 01:27:27 +00:00
( * quoted ) [ 0 ] = ' \' ' ;
2013-08-21 09:08:16 +00:00
* quotedlen = PQescapeStringConn ( H - > server , * quoted + 1 , unquoted , ( size_t ) unquotedlen , NULL ) ;
2005-02-06 01:27:27 +00:00
( * quoted ) [ * quotedlen + 1 ] = ' \' ' ;
( * quoted ) [ * quotedlen + 2 ] = ' \0 ' ;
* quotedlen + = 2 ;
}
2004-05-20 02:27:49 +00:00
return 1 ;
}
2005-02-26 17:27:51 +00:00
static char * pdo_pgsql_last_insert_id ( pdo_dbh_t * dbh , const char * name , unsigned int * len TSRMLS_DC )
2004-05-20 18:00:24 +00:00
{
pdo_pgsql_db_handle * H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
2005-02-26 17:27:51 +00:00
char * id = NULL ;
2005-07-01 21:54:50 +00:00
if ( name = = NULL ) {
2005-07-01 22:43:16 +00:00
if ( H - > pgoid = = InvalidOid ) {
return NULL ;
}
2005-07-01 21:54:50 +00:00
* len = spprintf ( & id , 0 , " %ld " , ( long ) H - > pgoid ) ;
} else {
PGresult * res ;
ExecStatusType status ;
2005-07-07 13:35:39 +00:00
const char * q [ 1 ] ;
q [ 0 ] = name ;
res = PQexecParams ( H - > server , " SELECT CURRVAL($1) " , 1 , NULL , q , NULL , NULL , 0 ) ;
2005-07-01 21:54:50 +00:00
status = PQresultStatus ( res ) ;
2005-02-26 17:27:51 +00:00
2005-07-01 21:54:50 +00:00
if ( res & & ( status = = PGRES_TUPLES_OK ) ) {
id = estrdup ( ( char * ) PQgetvalue ( res , 0 , 0 ) ) ;
* len = PQgetlength ( res , 0 , 0 ) ;
} else {
2005-07-01 22:30:55 +00:00
pdo_pgsql_error ( dbh , status , pdo_pgsql_sqlstate ( res ) ) ;
2005-07-01 21:54:50 +00:00
}
if ( res ) {
PQclear ( res ) ;
}
}
2005-02-26 17:27:51 +00:00
return id ;
2004-05-20 18:00:24 +00:00
}
2004-05-20 02:27:49 +00:00
2004-05-20 20:04:11 +00:00
static int pdo_pgsql_get_attribute ( pdo_dbh_t * dbh , long attr , zval * return_value TSRMLS_DC )
{
pdo_pgsql_db_handle * H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
switch ( attr ) {
case PDO_ATTR_CLIENT_VERSION :
ZVAL_STRING ( return_value , PG_VERSION , 1 ) ;
break ;
case PDO_ATTR_SERVER_VERSION :
if ( PQprotocolVersion ( H - > server ) > = 3 ) { /* PostgreSQL 7.4 or later */
ZVAL_STRING ( return_value , ( char * ) PQparameterStatus ( H - > server , " server_version " ) , 1 ) ;
} else /* emulate above via a query */
{
PGresult * res = PQexec ( H - > server , " SELECT VERSION() " ) ;
if ( res & & PQresultStatus ( res ) = = PGRES_TUPLES_OK ) {
ZVAL_STRING ( return_value , ( char * ) PQgetvalue ( res , 0 , 0 ) , 1 ) ;
}
if ( res ) {
PQclear ( res ) ;
}
}
break ;
case PDO_ATTR_CONNECTION_STATUS :
switch ( PQstatus ( H - > server ) ) {
case CONNECTION_STARTED :
ZVAL_STRINGL ( return_value , " Waiting for connection to be made. " , sizeof ( " Waiting for connection to be made. " ) - 1 , 1 ) ;
break ;
case CONNECTION_MADE :
case CONNECTION_OK :
ZVAL_STRINGL ( return_value , " Connection OK; waiting to send. " , sizeof ( " Connection OK; waiting to send. " ) - 1 , 1 ) ;
break ;
case CONNECTION_AWAITING_RESPONSE :
ZVAL_STRINGL ( return_value , " Waiting for a response from the server. " , sizeof ( " Waiting for a response from the server. " ) - 1 , 1 ) ;
break ;
case CONNECTION_AUTH_OK :
ZVAL_STRINGL ( return_value , " Received authentication; waiting for backend start-up to finish. " , sizeof ( " Received authentication; waiting for backend start-up to finish. " ) - 1 , 1 ) ;
break ;
# ifdef CONNECTION_SSL_STARTUP
case CONNECTION_SSL_STARTUP :
ZVAL_STRINGL ( return_value , " Negotiating SSL encryption. " , sizeof ( " Negotiating SSL encryption. " ) - 1 , 1 ) ;
break ;
# endif
case CONNECTION_SETENV :
ZVAL_STRINGL ( return_value , " Negotiating environment-driven parameter settings. " , sizeof ( " Negotiating environment-driven parameter settings. " ) - 1 , 1 ) ;
break ;
case CONNECTION_BAD :
default :
ZVAL_STRINGL ( return_value , " Bad connection. " , sizeof ( " Bad connection. " ) - 1 , 1 ) ;
break ;
}
break ;
case PDO_ATTR_SERVER_INFO : {
int spid = PQbackendPID ( H - > server ) ;
char * tmp ;
2014-03-09 10:43:13 +00:00
spprintf ( & tmp , 0 ,
" PID: %d; Client Encoding: %s; Is Superuser: %s; Session Authorization: %s; Date Style: %s " ,
2004-05-20 20:22:07 +00:00
spid ,
2004-05-20 20:04:11 +00:00
( char * ) PQparameterStatus ( H - > server , " client_encoding " ) ,
( char * ) PQparameterStatus ( H - > server , " is_superuser " ) ,
( char * ) PQparameterStatus ( H - > server , " session_authorization " ) ,
2004-05-20 20:22:07 +00:00
( char * ) PQparameterStatus ( H - > server , " DateStyle " ) ) ;
2004-05-20 20:04:11 +00:00
ZVAL_STRING ( return_value , tmp , 0 ) ;
}
break ;
default :
2014-03-09 10:43:13 +00:00
return 0 ;
2004-05-20 20:04:11 +00:00
}
return 1 ;
}
2007-06-27 02:00:46 +00:00
/* {{{ */
static int pdo_pgsql_check_liveness ( pdo_dbh_t * dbh TSRMLS_DC )
{
pdo_pgsql_db_handle * H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
if ( PQstatus ( H - > server ) = = CONNECTION_BAD ) {
PQreset ( H - > server ) ;
}
return ( PQstatus ( H - > server ) = = CONNECTION_OK ) ? SUCCESS : FAILURE ;
}
/* }}} */
2004-05-25 17:36:22 +00:00
static int pdo_pgsql_transaction_cmd ( const char * cmd , pdo_dbh_t * dbh TSRMLS_DC )
{
pdo_pgsql_db_handle * H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
PGresult * res ;
int ret = 1 ;
res = PQexec ( H - > server , cmd ) ;
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK ) {
2006-09-19 15:45:22 +00:00
pdo_pgsql_error ( dbh , PQresultStatus ( res ) , pdo_pgsql_sqlstate ( res ) ) ;
2004-05-25 17:38:58 +00:00
ret = 0 ;
2004-05-25 17:36:22 +00:00
}
PQclear ( res ) ;
return ret ;
}
static int pgsql_handle_begin ( pdo_dbh_t * dbh TSRMLS_DC )
{
2004-05-25 17:38:58 +00:00
return pdo_pgsql_transaction_cmd ( " BEGIN " , dbh TSRMLS_CC ) ;
2004-05-25 17:36:22 +00:00
}
static int pgsql_handle_commit ( pdo_dbh_t * dbh TSRMLS_DC )
{
2004-05-25 17:38:58 +00:00
return pdo_pgsql_transaction_cmd ( " COMMIT " , dbh TSRMLS_CC ) ;
2004-05-25 17:36:22 +00:00
}
static int pgsql_handle_rollback ( pdo_dbh_t * dbh TSRMLS_DC )
{
2004-05-25 17:38:58 +00:00
return pdo_pgsql_transaction_cmd ( " ROLLBACK " , dbh TSRMLS_CC ) ;
2004-05-25 17:36:22 +00:00
}
2004-05-20 20:04:11 +00:00
2010-06-10 12:11:19 +00:00
static int pgsql_handle_in_transaction ( pdo_dbh_t * dbh TSRMLS_DC )
{
pdo_pgsql_db_handle * H ;
H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
return PQtransactionStatus ( H - > server ) ;
}
2010-06-10 11:11:29 +00:00
/* {{{ proto string PDO::pgsqlCopyFromArray(string $table_name , array $rows [, string $delimiter [, string $null_as ] [, string $fields])
Returns true if the copy worked fine or false if error */
static PHP_METHOD ( PDO , pgsqlCopyFromArray )
{
pdo_dbh_t * dbh ;
pdo_pgsql_db_handle * H ;
zval * pg_rows ;
char * table_name , * pg_delim = NULL , * pg_null_as = NULL , * pg_fields = NULL ;
int table_name_len , pg_delim_len = 0 , pg_null_as_len = 0 , pg_fields_len ;
char * query ;
PGresult * pgsql_result ;
ExecStatusType status ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s/a|sss " ,
& table_name , & table_name_len , & pg_rows ,
& pg_delim , & pg_delim_len , & pg_null_as , & pg_null_as_len , & pg_fields , & pg_fields_len ) = = FAILURE ) {
return ;
}
if ( ! zend_hash_num_elements ( Z_ARRVAL_P ( pg_rows ) ) ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Cannot copy from an empty array " ) ;
RETURN_FALSE ;
}
dbh = zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
PDO_CONSTRUCT_CHECK ;
2013-06-04 15:20:20 +00:00
PDO_DBH_CLEAR_ERR ( ) ;
2010-06-10 11:11:29 +00:00
2013-06-07 07:23:00 +00:00
/* using pre-9.0 syntax as PDO_pgsql is 7.4+ compatible */
2010-06-10 11:11:29 +00:00
if ( pg_fields ) {
2013-06-07 07:23:00 +00:00
spprintf ( & query , 0 , " COPY %s (%s) FROM STDIN WITH DELIMITER E'%c' NULL AS E'%s' " , table_name , pg_fields , ( pg_delim_len ? * pg_delim : ' \t ' ) , ( pg_null_as_len ? pg_null_as : " \\ \\ N " ) ) ;
2010-06-10 11:11:29 +00:00
} else {
2013-06-07 07:23:00 +00:00
spprintf ( & query , 0 , " COPY %s FROM STDIN WITH DELIMITER E'%c' NULL AS E'%s' " , table_name , ( pg_delim_len ? * pg_delim : ' \t ' ) , ( pg_null_as_len ? pg_null_as : " \\ \\ N " ) ) ;
2010-06-10 11:11:29 +00:00
}
2011-06-10 23:14:15 +00:00
/* Obtain db Handle */
2010-06-10 11:11:29 +00:00
H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
while ( ( pgsql_result = PQgetResult ( H - > server ) ) ) {
PQclear ( pgsql_result ) ;
}
pgsql_result = PQexec ( H - > server , query ) ;
efree ( query ) ;
query = NULL ;
if ( pgsql_result ) {
status = PQresultStatus ( pgsql_result ) ;
} else {
status = ( ExecStatusType ) PQstatus ( H - > server ) ;
}
if ( status = = PGRES_COPY_IN & & pgsql_result ) {
int command_failed = 0 ;
int buffer_len = 0 ;
zval * * tmp ;
HashPosition pos ;
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 ) {
int query_len ;
convert_to_string_ex ( tmp ) ;
2014-03-09 10:43:13 +00:00
2010-06-10 11:11:29 +00:00
if ( buffer_len < Z_STRLEN_PP ( tmp ) ) {
buffer_len = Z_STRLEN_PP ( tmp ) ;
query = erealloc ( query , buffer_len + 2 ) ; /* room for \n\0 */
}
memcpy ( query , Z_STRVAL_PP ( tmp ) , Z_STRLEN_PP ( tmp ) ) ;
query_len = Z_STRLEN_PP ( tmp ) ;
if ( query [ query_len - 1 ] ! = ' \n ' ) {
query [ query_len + + ] = ' \n ' ;
}
query [ query_len ] = ' \0 ' ;
if ( PQputCopyData ( H - > server , query , query_len ) ! = 1 ) {
efree ( query ) ;
2013-06-04 15:20:20 +00:00
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , NULL ) ;
PDO_HANDLE_DBH_ERR ( ) ;
2010-06-10 11:11:29 +00:00
RETURN_FALSE ;
}
zend_hash_move_forward_ex ( Z_ARRVAL_P ( pg_rows ) , & pos ) ;
}
if ( query ) {
efree ( query ) ;
}
if ( PQputCopyEnd ( H - > server , NULL ) ! = 1 ) {
2013-06-04 15:20:20 +00:00
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , NULL ) ;
PDO_HANDLE_DBH_ERR ( ) ;
2010-06-10 11:11:29 +00:00
RETURN_FALSE ;
}
while ( ( pgsql_result = PQgetResult ( H - > server ) ) ) {
if ( PGRES_COMMAND_OK ! = PQresultStatus ( pgsql_result ) ) {
2013-06-04 15:20:20 +00:00
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , pdo_pgsql_sqlstate ( pgsql_result ) ) ;
2010-06-10 11:11:29 +00:00
command_failed = 1 ;
}
PQclear ( pgsql_result ) ;
}
2013-06-04 15:20:20 +00:00
PDO_HANDLE_DBH_ERR ( ) ;
2010-06-10 11:11:29 +00:00
RETURN_BOOL ( ! command_failed ) ;
} else {
2013-06-04 15:20:20 +00:00
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , pdo_pgsql_sqlstate ( pgsql_result ) ) ;
2010-06-10 11:11:29 +00:00
PQclear ( pgsql_result ) ;
2013-06-04 15:20:20 +00:00
PDO_HANDLE_DBH_ERR ( ) ;
2010-06-10 11:11:29 +00:00
RETURN_FALSE ;
}
}
/* }}} */
/* {{{ proto string PDO::pgsqlCopyFromFile(string $table_name , string $filename [, string $delimiter [, string $null_as ] [, string $fields])
Returns true if the copy worked fine or false if error */
static PHP_METHOD ( PDO , pgsqlCopyFromFile )
{
pdo_dbh_t * dbh ;
pdo_pgsql_db_handle * H ;
char * table_name , * filename , * pg_delim = NULL , * pg_null_as = NULL , * pg_fields = NULL ;
int table_name_len , filename_len , pg_delim_len = 0 , pg_null_as_len = 0 , pg_fields_len ;
char * query ;
PGresult * pgsql_result ;
ExecStatusType status ;
php_stream * stream ;
2011-06-06 21:28:16 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " sp|sss " ,
2010-06-10 11:11:29 +00:00
& table_name , & table_name_len , & filename , & filename_len ,
& pg_delim , & pg_delim_len , & pg_null_as , & pg_null_as_len , & pg_fields , & pg_fields_len ) = = FAILURE ) {
return ;
}
2011-06-10 23:14:15 +00:00
/* Obtain db Handler */
2010-06-10 11:11:29 +00:00
dbh = zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
PDO_CONSTRUCT_CHECK ;
2013-06-04 15:20:20 +00:00
PDO_DBH_CLEAR_ERR ( ) ;
2010-06-10 11:11:29 +00:00
2013-06-04 15:20:20 +00:00
stream = php_stream_open_wrapper_ex ( filename , " rb " , ENFORCE_SAFE_MODE , NULL , FG ( default_context ) ) ;
2010-06-10 11:11:29 +00:00
if ( ! stream ) {
2013-06-04 15:20:20 +00:00
pdo_pgsql_error_msg ( dbh , PGRES_FATAL_ERROR , " Unable to open the file " ) ;
PDO_HANDLE_DBH_ERR ( ) ;
2010-06-10 11:11:29 +00:00
RETURN_FALSE ;
}
2013-06-07 07:23:00 +00:00
/* using pre-9.0 syntax as PDO_pgsql is 7.4+ compatible */
2010-06-10 11:11:29 +00:00
if ( pg_fields ) {
2013-06-07 07:23:00 +00:00
spprintf ( & query , 0 , " COPY %s (%s) FROM STDIN WITH DELIMITER E'%c' NULL AS E'%s' " , table_name , pg_fields , ( pg_delim_len ? * pg_delim : ' \t ' ) , ( pg_null_as_len ? pg_null_as : " \\ \\ N " ) ) ;
2010-06-10 11:11:29 +00:00
} else {
2013-06-07 07:23:00 +00:00
spprintf ( & query , 0 , " COPY %s FROM STDIN WITH DELIMITER E'%c' NULL AS E'%s' " , table_name , ( pg_delim_len ? * pg_delim : ' \t ' ) , ( pg_null_as_len ? pg_null_as : " \\ \\ N " ) ) ;
2010-06-10 11:11:29 +00:00
}
H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
while ( ( pgsql_result = PQgetResult ( H - > server ) ) ) {
PQclear ( pgsql_result ) ;
}
pgsql_result = PQexec ( H - > server , query ) ;
efree ( query ) ;
if ( pgsql_result ) {
status = PQresultStatus ( pgsql_result ) ;
} else {
status = ( ExecStatusType ) PQstatus ( H - > server ) ;
}
if ( status = = PGRES_COPY_IN & & pgsql_result ) {
char * buf ;
int command_failed = 0 ;
size_t line_len = 0 ;
PQclear ( pgsql_result ) ;
while ( ( buf = php_stream_get_line ( stream , NULL , 0 , & line_len ) ) ! = NULL ) {
if ( PQputCopyData ( H - > server , buf , line_len ) ! = 1 ) {
efree ( buf ) ;
2013-06-04 15:20:20 +00:00
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , NULL ) ;
2010-06-10 11:11:29 +00:00
php_stream_close ( stream ) ;
2013-06-04 15:20:20 +00:00
PDO_HANDLE_DBH_ERR ( ) ;
2010-06-10 11:11:29 +00:00
RETURN_FALSE ;
}
efree ( buf ) ;
}
php_stream_close ( stream ) ;
if ( PQputCopyEnd ( H - > server , NULL ) ! = 1 ) {
2013-06-04 15:20:20 +00:00
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , NULL ) ;
PDO_HANDLE_DBH_ERR ( ) ;
2010-06-10 11:11:29 +00:00
RETURN_FALSE ;
}
while ( ( pgsql_result = PQgetResult ( H - > server ) ) ) {
if ( PGRES_COMMAND_OK ! = PQresultStatus ( pgsql_result ) ) {
2013-06-04 15:20:20 +00:00
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , pdo_pgsql_sqlstate ( pgsql_result ) ) ;
2010-06-10 11:11:29 +00:00
command_failed = 1 ;
}
PQclear ( pgsql_result ) ;
}
2013-06-04 15:20:20 +00:00
PDO_HANDLE_DBH_ERR ( ) ;
2010-06-10 11:11:29 +00:00
RETURN_BOOL ( ! command_failed ) ;
} else {
php_stream_close ( stream ) ;
2013-06-04 15:20:20 +00:00
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , pdo_pgsql_sqlstate ( pgsql_result ) ) ;
PQclear ( pgsql_result ) ;
PDO_HANDLE_DBH_ERR ( ) ;
2010-06-10 11:11:29 +00:00
RETURN_FALSE ;
}
}
/* }}} */
/* {{{ proto string PDO::pgsqlCopyToFile(string $table_name , $filename, [string $delimiter [, string $null_as [, string $fields]]])
Returns true if the copy worked fine or false if error */
static PHP_METHOD ( PDO , pgsqlCopyToFile )
{
pdo_dbh_t * dbh ;
pdo_pgsql_db_handle * H ;
char * table_name , * pg_delim = NULL , * pg_null_as = NULL , * pg_fields = NULL , * filename = NULL ;
int table_name_len , pg_delim_len = 0 , pg_null_as_len = 0 , pg_fields_len , filename_len ;
char * query ;
PGresult * pgsql_result ;
ExecStatusType status ;
php_stream * stream ;
2011-06-06 21:28:16 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " sp|sss " ,
2010-06-10 11:11:29 +00:00
& table_name , & table_name_len , & filename , & filename_len ,
& pg_delim , & pg_delim_len , & pg_null_as , & pg_null_as_len , & pg_fields , & pg_fields_len ) = = FAILURE ) {
return ;
}
dbh = zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
PDO_CONSTRUCT_CHECK ;
2013-06-04 15:20:20 +00:00
PDO_DBH_CLEAR_ERR ( ) ;
2010-06-10 11:11:29 +00:00
H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
2013-06-04 15:20:20 +00:00
stream = php_stream_open_wrapper_ex ( filename , " wb " , ENFORCE_SAFE_MODE , NULL , FG ( default_context ) ) ;
2010-06-10 11:11:29 +00:00
if ( ! stream ) {
2013-06-04 15:20:20 +00:00
pdo_pgsql_error_msg ( dbh , PGRES_FATAL_ERROR , " Unable to open the file for writing " ) ;
PDO_HANDLE_DBH_ERR ( ) ;
2010-06-10 11:11:29 +00:00
RETURN_FALSE ;
}
while ( ( pgsql_result = PQgetResult ( H - > server ) ) ) {
PQclear ( pgsql_result ) ;
}
2013-06-07 07:23:00 +00:00
/* using pre-9.0 syntax as PDO_pgsql is 7.4+ compatible */
2010-06-10 11:11:29 +00:00
if ( pg_fields ) {
2013-06-07 07:23:00 +00:00
spprintf ( & query , 0 , " COPY %s (%s) TO STDIN WITH DELIMITER E'%c' NULL AS E'%s' " , table_name , pg_fields , ( pg_delim_len ? * pg_delim : ' \t ' ) , ( pg_null_as_len ? pg_null_as : " \\ \\ N " ) ) ;
2010-06-10 11:11:29 +00:00
} else {
2013-06-07 07:23:00 +00:00
spprintf ( & query , 0 , " COPY %s TO STDIN WITH DELIMITER E'%c' NULL AS E'%s' " , table_name , ( pg_delim_len ? * pg_delim : ' \t ' ) , ( pg_null_as_len ? pg_null_as : " \\ \\ N " ) ) ;
2010-06-10 11:11:29 +00:00
}
pgsql_result = PQexec ( H - > server , query ) ;
efree ( query ) ;
if ( pgsql_result ) {
status = PQresultStatus ( pgsql_result ) ;
} else {
status = ( ExecStatusType ) PQstatus ( H - > server ) ;
}
if ( status = = PGRES_COPY_OUT & & pgsql_result ) {
PQclear ( pgsql_result ) ;
while ( 1 ) {
char * csv = NULL ;
int ret = PQgetCopyData ( H - > server , & csv , 0 ) ;
if ( ret = = - 1 ) {
break ; /* done */
} else if ( ret > 0 ) {
if ( php_stream_write ( stream , csv , ret ) ! = ret ) {
2013-06-04 15:20:20 +00:00
pdo_pgsql_error_msg ( dbh , PGRES_FATAL_ERROR , " Unable to write to file " ) ;
2010-06-10 11:11:29 +00:00
PQfreemem ( csv ) ;
php_stream_close ( stream ) ;
2013-06-04 15:20:20 +00:00
PDO_HANDLE_DBH_ERR ( ) ;
2010-06-10 11:11:29 +00:00
RETURN_FALSE ;
} else {
PQfreemem ( csv ) ;
}
} else {
2013-06-04 15:20:20 +00:00
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , NULL ) ;
2010-06-10 11:11:29 +00:00
php_stream_close ( stream ) ;
2013-06-04 15:20:20 +00:00
PDO_HANDLE_DBH_ERR ( ) ;
2010-06-10 11:11:29 +00:00
RETURN_FALSE ;
}
}
php_stream_close ( stream ) ;
while ( ( pgsql_result = PQgetResult ( H - > server ) ) ) {
PQclear ( pgsql_result ) ;
}
RETURN_TRUE ;
} else {
php_stream_close ( stream ) ;
2013-06-04 15:20:20 +00:00
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , pdo_pgsql_sqlstate ( pgsql_result ) ) ;
2010-06-10 11:11:29 +00:00
PQclear ( pgsql_result ) ;
2013-06-04 15:20:20 +00:00
PDO_HANDLE_DBH_ERR ( ) ;
2010-06-10 11:11:29 +00:00
RETURN_FALSE ;
}
}
/* }}} */
/* {{{ proto string PDO::pgsqlCopyToArray(string $table_name , [string $delimiter [, string $null_as [, string $fields]]])
Returns true if the copy worked fine or false if error */
static PHP_METHOD ( PDO , pgsqlCopyToArray )
{
pdo_dbh_t * dbh ;
pdo_pgsql_db_handle * H ;
char * table_name , * pg_delim = NULL , * pg_null_as = NULL , * pg_fields = NULL ;
int table_name_len , pg_delim_len = 0 , pg_null_as_len = 0 , pg_fields_len ;
char * query ;
PGresult * pgsql_result ;
ExecStatusType status ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s|sss " ,
& table_name , & table_name_len ,
& pg_delim , & pg_delim_len , & pg_null_as , & pg_null_as_len , & pg_fields , & pg_fields_len ) = = FAILURE ) {
return ;
}
dbh = zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
PDO_CONSTRUCT_CHECK ;
2013-06-04 15:20:20 +00:00
PDO_DBH_CLEAR_ERR ( ) ;
2010-06-10 11:11:29 +00:00
H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
while ( ( pgsql_result = PQgetResult ( H - > server ) ) ) {
PQclear ( pgsql_result ) ;
}
2013-06-07 07:23:00 +00:00
/* using pre-9.0 syntax as PDO_pgsql is 7.4+ compatible */
2010-06-10 11:11:29 +00:00
if ( pg_fields ) {
2013-06-07 07:23:00 +00:00
spprintf ( & query , 0 , " COPY %s (%s) TO STDIN WITH DELIMITER E'%c' NULL AS E'%s' " , table_name , pg_fields , ( pg_delim_len ? * pg_delim : ' \t ' ) , ( pg_null_as_len ? pg_null_as : " \\ \\ N " ) ) ;
2010-06-10 11:11:29 +00:00
} else {
2013-06-07 07:23:00 +00:00
spprintf ( & query , 0 , " COPY %s TO STDIN WITH DELIMITER E'%c' NULL AS E'%s' " , table_name , ( pg_delim_len ? * pg_delim : ' \t ' ) , ( pg_null_as_len ? pg_null_as : " \\ \\ N " ) ) ;
2010-06-10 11:11:29 +00:00
}
pgsql_result = PQexec ( H - > server , query ) ;
efree ( query ) ;
if ( pgsql_result ) {
status = PQresultStatus ( pgsql_result ) ;
} else {
status = ( ExecStatusType ) PQstatus ( H - > server ) ;
}
if ( status = = PGRES_COPY_OUT & & pgsql_result ) {
PQclear ( pgsql_result ) ;
array_init ( return_value ) ;
while ( 1 ) {
char * csv = NULL ;
int ret = PQgetCopyData ( H - > server , & csv , 0 ) ;
if ( ret = = - 1 ) {
break ; /* copy done */
2014-03-09 10:43:13 +00:00
} else if ( ret > 0 ) {
2014-04-15 11:40:40 +00:00
add_next_index_stringl ( return_value , csv , ret ) ;
2010-06-10 11:11:29 +00:00
PQfreemem ( csv ) ;
} else {
2013-06-04 15:20:20 +00:00
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , NULL ) ;
PDO_HANDLE_DBH_ERR ( ) ;
2010-06-10 11:11:29 +00:00
RETURN_FALSE ;
}
}
while ( ( pgsql_result = PQgetResult ( H - > server ) ) ) {
PQclear ( pgsql_result ) ;
}
} else {
2013-06-04 15:20:20 +00:00
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , pdo_pgsql_sqlstate ( pgsql_result ) ) ;
2010-06-10 11:11:29 +00:00
PQclear ( pgsql_result ) ;
2013-06-04 15:20:20 +00:00
PDO_HANDLE_DBH_ERR ( ) ;
2010-06-10 11:11:29 +00:00
RETURN_FALSE ;
}
}
/* }}} */
2005-11-29 04:06:03 +00:00
/* {{{ proto string PDO::pgsqlLOBCreate()
2005-11-29 02:11:39 +00:00
Creates a new large object , returning its identifier . Must be called inside a transaction . */
2005-11-29 04:06:03 +00:00
static PHP_METHOD ( PDO , pgsqlLOBCreate )
2005-11-29 02:11:39 +00:00
{
pdo_dbh_t * dbh ;
pdo_pgsql_db_handle * H ;
Oid lfd ;
dbh = zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
PDO_CONSTRUCT_CHECK ;
2013-06-04 15:20:20 +00:00
PDO_DBH_CLEAR_ERR ( ) ;
2005-11-29 02:11:39 +00:00
H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
lfd = lo_creat ( H - > server , INV_READ | INV_WRITE ) ;
if ( lfd ! = InvalidOid ) {
char * buf ;
2005-11-29 18:17:46 +00:00
spprintf ( & buf , 0 , " %lu " , ( long ) lfd ) ;
2005-11-29 02:11:39 +00:00
RETURN_STRING ( buf , 0 ) ;
}
2013-06-04 15:20:20 +00:00
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , NULL ) ;
PDO_HANDLE_DBH_ERR ( ) ;
2005-11-29 02:11:39 +00:00
RETURN_FALSE ;
}
/* }}} */
2005-11-29 04:06:03 +00:00
/* {{{ proto resource PDO::pgsqlLOBOpen(string oid [, string mode = 'rb'])
2005-11-29 02:11:39 +00:00
Opens an existing large object stream . Must be called inside a transaction . */
2005-11-29 04:06:03 +00:00
static PHP_METHOD ( PDO , pgsqlLOBOpen )
2005-11-29 02:11:39 +00:00
{
pdo_dbh_t * dbh ;
pdo_pgsql_db_handle * H ;
Oid oid ;
int lfd ;
char * oidstr ;
int oidstrlen ;
char * modestr = " rb " ;
int modestrlen ;
int mode = INV_READ ;
char * end_ptr ;
if ( FAILURE = = zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s|s " ,
& oidstr , & oidstrlen , & modestr , & modestrlen ) ) {
RETURN_FALSE ;
}
oid = ( Oid ) strtoul ( oidstr , & end_ptr , 10 ) ;
if ( oid = = 0 & & ( errno = = ERANGE | | errno = = EINVAL ) ) {
RETURN_FALSE ;
}
if ( strpbrk ( modestr , " +w " ) ) {
mode = INV_READ | INV_WRITE ;
}
2014-03-09 10:43:13 +00:00
2005-11-29 02:11:39 +00:00
dbh = zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
PDO_CONSTRUCT_CHECK ;
2013-06-04 15:20:20 +00:00
PDO_DBH_CLEAR_ERR ( ) ;
2005-11-29 02:11:39 +00:00
H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
lfd = lo_open ( H - > server , oid , mode ) ;
if ( lfd > = 0 ) {
php_stream * stream = pdo_pgsql_create_lob_stream ( dbh , lfd , oid TSRMLS_CC ) ;
if ( stream ) {
php_stream_to_zval ( stream , return_value ) ;
return ;
}
} else {
2013-06-04 15:20:20 +00:00
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , NULL ) ;
2005-11-29 02:11:39 +00:00
}
2013-06-04 15:20:20 +00:00
PDO_HANDLE_DBH_ERR ( ) ;
2005-11-29 02:11:39 +00:00
RETURN_FALSE ;
}
/* }}} */
2005-11-29 04:06:03 +00:00
/* {{{ proto bool PDO::pgsqlLOBUnlink(string oid)
2005-11-29 02:11:39 +00:00
Deletes the large object identified by oid . Must be called inside a transaction . */
2005-11-29 04:06:03 +00:00
static PHP_METHOD ( PDO , pgsqlLOBUnlink )
2005-11-29 02:11:39 +00:00
{
pdo_dbh_t * dbh ;
pdo_pgsql_db_handle * H ;
2005-11-29 04:06:03 +00:00
Oid oid ;
char * oidstr , * end_ptr ;
int oidlen ;
if ( FAILURE = = zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s " ,
& oidstr , & oidlen ) ) {
RETURN_FALSE ;
}
2005-11-29 02:11:39 +00:00
2005-11-29 04:06:03 +00:00
oid = ( Oid ) strtoul ( oidstr , & end_ptr , 10 ) ;
if ( oid = = 0 & & ( errno = = ERANGE | | errno = = EINVAL ) ) {
2005-11-29 02:11:39 +00:00
RETURN_FALSE ;
}
dbh = zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
PDO_CONSTRUCT_CHECK ;
2013-06-04 15:20:20 +00:00
PDO_DBH_CLEAR_ERR ( ) ;
2005-11-29 02:11:39 +00:00
H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
2013-06-04 15:20:20 +00:00
2005-11-29 04:06:03 +00:00
if ( 1 = = lo_unlink ( H - > server , oid ) ) {
2005-11-29 02:11:39 +00:00
RETURN_TRUE ;
}
2013-06-04 15:20:20 +00:00
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , NULL ) ;
PDO_HANDLE_DBH_ERR ( ) ;
2005-11-29 02:11:39 +00:00
RETURN_FALSE ;
}
2005-11-29 04:06:03 +00:00
/* }}} */
2005-11-29 02:11:39 +00:00
2013-06-02 12:00:40 +00:00
/* {{{ proto mixed PDO::pgsqlGetNotify([ int $result_type = PDO::FETCH_USE_DEFAULT] [, int $ms_timeout = 0 ]])
Get asyncronous notification */
static PHP_METHOD ( PDO , pgsqlGetNotify )
{
pdo_dbh_t * dbh ;
pdo_pgsql_db_handle * H ;
long result_type = PDO_FETCH_USE_DEFAULT ;
long ms_timeout = 0 ;
PGnotify * pgsql_notify ;
if ( FAILURE = = zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " |ll " ,
& result_type , & ms_timeout ) ) {
RETURN_FALSE ;
}
dbh = zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
PDO_CONSTRUCT_CHECK ;
if ( result_type = = PDO_FETCH_USE_DEFAULT ) {
result_type = dbh - > default_fetch_type ;
}
if ( result_type ! = PDO_FETCH_BOTH & & result_type ! = PDO_FETCH_ASSOC & & result_type ! = PDO_FETCH_NUM ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid result type " ) ;
RETURN_FALSE ;
}
if ( ms_timeout < 0 ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid timeout " ) ;
RETURN_FALSE ;
}
H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
PQconsumeInput ( H - > server ) ;
pgsql_notify = PQnotifies ( H - > server ) ;
if ( ms_timeout & & ! pgsql_notify ) {
php_pollfd_for_ms ( PQsocket ( H - > server ) , PHP_POLLREADABLE , ms_timeout ) ;
PQconsumeInput ( H - > server ) ;
pgsql_notify = PQnotifies ( H - > server ) ;
}
if ( ! pgsql_notify ) {
RETURN_FALSE ;
}
array_init ( return_value ) ;
if ( result_type = = PDO_FETCH_NUM | | result_type = = PDO_FETCH_BOTH ) {
2014-04-15 11:40:40 +00:00
add_index_string ( return_value , 0 , pgsql_notify - > relname ) ;
2013-06-02 12:00:40 +00:00
add_index_long ( return_value , 1 , pgsql_notify - > be_pid ) ;
}
if ( result_type = = PDO_FETCH_ASSOC | | result_type = = PDO_FETCH_BOTH ) {
2014-04-15 11:40:40 +00:00
add_assoc_string ( return_value , " message " , pgsql_notify - > relname ) ;
2013-06-02 12:00:40 +00:00
add_assoc_long ( return_value , " pid " , pgsql_notify - > be_pid ) ;
}
PQfreemem ( pgsql_notify ) ;
}
/* }}} */
/* {{{ proto int PDO::pgsqlGetPid()
Get backend ( server ) pid */
static PHP_METHOD ( PDO , pgsqlGetPid )
{
pdo_dbh_t * dbh ;
pdo_pgsql_db_handle * H ;
dbh = zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
PDO_CONSTRUCT_CHECK ;
H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
RETURN_LONG ( PQbackendPID ( H - > server ) ) ;
}
/* }}} */
2005-11-29 02:11:39 +00:00
2007-09-27 18:00:48 +00:00
static const zend_function_entry dbh_methods [ ] = {
2005-11-29 04:06:03 +00:00
PHP_ME ( PDO , pgsqlLOBCreate , NULL , ZEND_ACC_PUBLIC )
PHP_ME ( PDO , pgsqlLOBOpen , NULL , ZEND_ACC_PUBLIC )
PHP_ME ( PDO , pgsqlLOBUnlink , NULL , ZEND_ACC_PUBLIC )
2010-06-10 11:11:29 +00:00
PHP_ME ( PDO , pgsqlCopyFromArray , NULL , ZEND_ACC_PUBLIC )
PHP_ME ( PDO , pgsqlCopyFromFile , NULL , ZEND_ACC_PUBLIC )
PHP_ME ( PDO , pgsqlCopyToArray , NULL , ZEND_ACC_PUBLIC )
PHP_ME ( PDO , pgsqlCopyToFile , NULL , ZEND_ACC_PUBLIC )
2013-06-02 12:00:40 +00:00
PHP_ME ( PDO , pgsqlGetNotify , NULL , ZEND_ACC_PUBLIC )
PHP_ME ( PDO , pgsqlGetPid , NULL , ZEND_ACC_PUBLIC )
2011-07-25 11:35:02 +00:00
PHP_FE_END
2005-11-29 02:11:39 +00:00
} ;
2007-09-27 18:00:48 +00:00
static const zend_function_entry * pdo_pgsql_get_driver_methods ( pdo_dbh_t * dbh , int kind TSRMLS_DC )
2005-11-29 02:11:39 +00:00
{
switch ( kind ) {
case PDO_DBH_DRIVER_METHOD_KIND_DBH :
return dbh_methods ;
default :
return NULL ;
}
}
2006-12-18 17:56:25 +00:00
static int pdo_pgsql_set_attr ( pdo_dbh_t * dbh , long attr , zval * val TSRMLS_DC )
{
2009-10-07 17:40:16 +00:00
pdo_pgsql_db_handle * H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
switch ( attr ) {
case PDO_ATTR_EMULATE_PREPARES :
H - > emulate_prepares = Z_LVAL_P ( val ) ;
return 1 ;
case PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT :
2014-03-09 11:14:23 +00:00
php_error_docref ( NULL TSRMLS_CC , E_DEPRECATED , " PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT is deprecated, use PDO::ATTR_EMULATE_PREPARES instead " ) ;
2009-10-07 17:40:16 +00:00
H - > disable_native_prepares = Z_LVAL_P ( val ) ;
return 1 ;
2014-03-09 13:08:17 +00:00
case PDO_PGSQL_ATTR_DISABLE_PREPARES :
H - > disable_prepares = Z_LVAL_P ( val ) ;
return 1 ;
2009-10-07 17:40:16 +00:00
default :
return 0 ;
}
2006-12-18 17:56:25 +00:00
}
2004-05-20 02:27:49 +00:00
static struct pdo_dbh_methods pgsql_methods = {
pgsql_handle_closer ,
pgsql_handle_preparer ,
pgsql_handle_doer ,
2004-05-20 17:43:56 +00:00
pgsql_handle_quoter ,
2004-05-25 17:36:22 +00:00
pgsql_handle_begin ,
pgsql_handle_commit ,
pgsql_handle_rollback ,
2006-12-18 17:56:25 +00:00
pdo_pgsql_set_attr ,
2004-05-20 18:00:24 +00:00
pdo_pgsql_last_insert_id ,
2004-05-20 20:04:11 +00:00
pdo_pgsql_fetch_error_func ,
2004-09-23 20:43:11 +00:00
pdo_pgsql_get_attribute ,
2007-06-27 02:00:46 +00:00
pdo_pgsql_check_liveness , /* check_liveness */
2010-06-10 12:11:19 +00:00
pdo_pgsql_get_driver_methods , /* get_driver_methods */
NULL ,
pgsql_handle_in_transaction ,
2004-05-20 02:27:49 +00:00
} ;
static int pdo_pgsql_handle_factory ( pdo_dbh_t * dbh , zval * driver_options TSRMLS_DC ) /* { { { */
{
pdo_pgsql_db_handle * H ;
2004-05-20 19:58:51 +00:00
int ret = 0 ;
2004-07-29 00:18:02 +00:00
char * conn_str , * p , * e ;
2014-01-19 00:24:22 +00:00
char * tmp_pass ;
2007-06-28 03:13:29 +00:00
long connect_timeout = 30 ;
2004-05-20 02:27:49 +00:00
H = pecalloc ( 1 , sizeof ( pdo_pgsql_db_handle ) , dbh - > is_persistent ) ;
dbh - > driver_data = H ;
2004-05-20 18:19:03 +00:00
H - > einfo . errcode = 0 ;
H - > einfo . errmsg = NULL ;
2014-03-09 10:43:13 +00:00
2004-07-29 00:18:02 +00:00
/* PostgreSQL wants params in the connect string to be separated by spaces,
* if the PDO standard semicolons are used , we convert them to spaces
*/
e = ( char * ) dbh - > data_source + strlen ( dbh - > data_source ) ;
p = ( char * ) dbh - > data_source ;
while ( ( p = memchr ( p , ' ; ' , ( e - p ) ) ) ) {
* p = ' ' ;
}
2007-06-28 03:13:29 +00:00
if ( driver_options ) {
connect_timeout = pdo_attr_lval ( driver_options , PDO_ATTR_TIMEOUT , 30 TSRMLS_CC ) ;
}
2014-01-19 00:24:22 +00:00
if ( dbh - > password ) {
if ( dbh - > password [ 0 ] ! = ' \' ' & & dbh - > password [ strlen ( dbh - > password ) - 1 ] ! = ' \' ' ) {
char * pwd = dbh - > password ;
int pos = 1 ;
tmp_pass = safe_emalloc ( 2 , strlen ( dbh - > password ) , 3 ) ;
tmp_pass [ 0 ] = ' \' ' ;
while ( * pwd ! = ' \0 ' ) {
if ( * pwd = = ' \\ ' | | * pwd = = ' \' ' ) {
tmp_pass [ pos + + ] = ' \\ ' ;
}
tmp_pass [ pos + + ] = * pwd + + ;
}
tmp_pass [ pos + + ] = ' \' ' ;
tmp_pass [ pos ] = ' \0 ' ;
} else {
tmp_pass = dbh - > password ;
}
}
2004-07-20 00:33:21 +00:00
/* support both full connection string & connection string + login and/or password */
2007-12-04 13:03:26 +00:00
if ( dbh - > username & & dbh - > password ) {
2014-01-19 00:24:22 +00:00
spprintf ( & conn_str , 0 , " %s user=%s password=%s connect_timeout=%ld " , dbh - > data_source , dbh - > username , tmp_pass , connect_timeout ) ;
2004-07-20 00:33:21 +00:00
} else if ( dbh - > username ) {
2007-06-28 03:13:29 +00:00
spprintf ( & conn_str , 0 , " %s user=%s connect_timeout=%ld " , dbh - > data_source , dbh - > username , connect_timeout ) ;
2007-12-04 13:03:26 +00:00
} else if ( dbh - > password ) {
2014-01-19 00:24:22 +00:00
spprintf ( & conn_str , 0 , " %s password=%s connect_timeout=%ld " , dbh - > data_source , tmp_pass , connect_timeout ) ;
2007-12-04 13:03:26 +00:00
} else {
spprintf ( & conn_str , 0 , " %s connect_timeout=%ld " , ( char * ) dbh - > data_source , connect_timeout ) ;
2004-07-20 00:33:21 +00:00
}
2005-02-03 22:24:50 +00:00
H - > server = PQconnectdb ( conn_str ) ;
2014-01-19 00:24:22 +00:00
if ( dbh - > password & & tmp_pass ! = dbh - > password ) {
efree ( tmp_pass ) ;
}
2007-06-28 03:13:29 +00:00
efree ( conn_str ) ;
2004-05-20 02:27:49 +00:00
if ( PQstatus ( H - > server ) ! = CONNECTION_OK ) {
2005-05-13 18:09:03 +00:00
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , PHP_PDO_PGSQL_CONNECTION_FAILURE_SQLSTATE ) ;
2004-05-20 02:27:49 +00:00
goto cleanup ;
}
2005-02-20 19:26:27 +00:00
PQsetNoticeProcessor ( H - > server , ( void ( * ) ( void * , const char * ) ) _pdo_pgsql_notice , ( void * ) & dbh ) ;
2004-05-20 02:27:49 +00:00
H - > attached = 1 ;
2004-05-20 18:00:24 +00:00
H - > pgoid = - 1 ;
2004-05-20 02:27:49 +00:00
dbh - > methods = & pgsql_methods ;
2006-02-13 15:53:36 +00:00
dbh - > alloc_own_columns = 1 ;
2004-05-20 02:27:49 +00:00
dbh - > max_escaped_char_length = 2 ;
ret = 1 ;
2014-03-09 10:43:13 +00:00
2004-05-20 02:27:49 +00:00
cleanup :
2004-07-28 00:15:19 +00:00
dbh - > methods = & pgsql_methods ;
2004-05-20 02:27:49 +00:00
if ( ! ret ) {
pgsql_handle_closer ( dbh TSRMLS_CC ) ;
}
return ret ;
}
/* }}} */
pdo_driver_t pdo_pgsql_driver = {
PDO_DRIVER_HEADER ( pgsql ) ,
pdo_pgsql_handle_factory
} ;
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* End :
* vim600 : noet sw = 4 ts = 4 fdm = marker
* vim < 600 : noet sw = 4 ts = 4
*/