2004-05-20 02:27:49 +00:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| PHP Version 5 |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2007-12-31 07:17:19 +00:00
| Copyright ( c ) 1997 - 2008 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"
# include "pdo/php_pdo.h"
# include "pdo/php_pdo_driver.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 ' ;
return tmp ;
2004-07-28 00:51:48 +00:00
}
2005-05-13 18:09:03 +00:00
int _pdo_pgsql_error ( pdo_dbh_t * dbh , pdo_stmt_t * stmt , int errcode , const char * sqlstate , 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 ;
}
2005-05-13 18:09:03 +00:00
if ( sqlstate = = NULL ) {
strcpy ( * pdo_err , " HY000 " ) ;
}
else {
strcpy ( * pdo_err , sqlstate ) ;
2004-05-20 17:43:56 +00:00
}
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 ) {
2005-01-07 05:25:57 +00:00
zend_throw_exception_ex ( php_pdo_get_exception ( ) , 0 TSRMLS_CC , " SQLSTATE[%s] [%d] %s " ,
* pdo_err , einfo - > errcode , einfo - > errmsg ) ;
2004-07-28 00:40:01 +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 ) ;
add_next_index_string ( info , einfo - > errmsg , 1 ) ;
}
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
# if HAVE_PQPREPARE
int ret ;
char * nsql = NULL ;
int nsql_len = 0 ;
2006-04-09 08:17:50 +00:00
int emulate = 0 ;
2005-07-08 15:27:34 +00:00
# endif
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 ) ;
}
2005-07-08 15:27:34 +00:00
/* TODO: check how scrollable cursors related to prepared statements */
2005-02-12 20:55:28 +00:00
spprintf ( & S - > cursor_name , 0 , " pdo_pgsql_cursor_%08x " , ( unsigned int ) stmt ) ;
2005-01-13 01:59:39 +00:00
}
2005-07-08 15:27:34 +00:00
# if HAVE_PQPREPARE
2006-04-09 08:17:50 +00:00
if ( driver_options ) {
if ( pdo_attr_lval ( driver_options ,
PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT , 0 TSRMLS_CC ) = = 1 ) {
emulate = 1 ;
} else if ( pdo_attr_lval ( driver_options , PDO_ATTR_EMULATE_PREPARES ,
0 TSRMLS_CC ) = = 1 ) {
emulate = 1 ;
}
}
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
2005-07-20 02:37:57 +00:00
spprintf ( & S - > stmt_name , 0 , " pdo_pgsql_stmt_%08x " , ( unsigned int ) stmt ) ;
2005-11-25 03:35:04 +00:00
/* that's all for now; we'll defer the actual prepare until the first execute call */
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
}
# endif
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 ;
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 ) ;
# if HAVE_PQCMDTUPLES
ret = atol ( PQcmdTuples ( res ) ) ;
# endif
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 ;
2005-02-06 01:27:27 +00:00
switch ( paramtype ) {
case PDO_PARAM_LOB :
/* escapedlen returned by PQescapeBytea() accounts for trailing 0 */
2006-10-06 22:34:16 +00:00
# ifdef HAVE_PQESCAPE_BYTEA_CONN
escaped = PQescapeByteaConn ( H - > server , unquoted , unquotedlen , quotedlen ) ;
# else
2005-02-06 01:27:27 +00:00
escaped = PQescapeBytea ( unquoted , unquotedlen , quotedlen ) ;
2006-10-06 22:34:16 +00:00
# endif
2005-02-06 01:27:27 +00:00
* quotedlen + = 1 ;
* 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 ] = ' \' ' ;
2006-10-04 23:53:36 +00:00
# ifndef HAVE_PQESCAPE_CONN
2005-02-06 01:27:27 +00:00
* quotedlen = PQescapeString ( * quoted + 1 , unquoted , unquotedlen ) ;
2006-10-04 23:53:36 +00:00
# else
* quotedlen = PQescapeStringConn ( H - > server , * quoted + 1 , unquoted , unquotedlen , NULL ) ;
# endif
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
# ifdef HAVE_PQEXECPARAMS
const char * q [ 1 ] ;
q [ 0 ] = name ;
res = PQexecParams ( H - > server , " SELECT CURRVAL($1) " , 1 , NULL , q , NULL , NULL , 0 ) ;
# else
char * name_escaped , * q ;
size_t l = strlen ( name ) ;
name_escaped = safe_emalloc ( l , 2 , 1 ) ;
2006-10-04 23:53:36 +00:00
# ifndef HAVE_PQESCAPE_CONN
2005-07-07 13:35:39 +00:00
PQescapeString ( name_escaped , name , l ) ;
2006-10-04 23:53:36 +00:00
# else
PQescapeStringConn ( H - > server , name_escaped , name , l , NULL ) ;
# endif
2005-07-07 13:35:39 +00:00
spprintf ( & q , 0 , " SELECT CURRVAL('%s') " , name_escaped ) ;
2005-07-01 21:54:50 +00:00
res = PQexec ( H - > server , q ) ;
2005-07-07 13:35:39 +00:00
efree ( name_escaped ) ;
2005-07-01 21:54:50 +00:00
efree ( q ) ;
2005-07-07 13:35:39 +00:00
# endif
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 :
# ifdef HAVE_PQPROTOCOLVERSION
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 */
# endif
{
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 ;
# ifdef HAVE_PQPROTOCOLVERSION
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
# else
spprintf ( & tmp , 0 , " PID: %d " , spid ) ;
# endif
ZVAL_STRING ( return_value , tmp , 0 ) ;
}
break ;
default :
return 0 ;
}
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
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 ;
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 ) ;
}
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , " HY000 " ) ;
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 ;
}
dbh = zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
PDO_CONSTRUCT_CHECK ;
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 {
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , " HY000 " ) ;
}
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 ;
H = ( pdo_pgsql_db_handle * ) dbh - > driver_data ;
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 ;
}
pdo_pgsql_error ( dbh , PGRES_FATAL_ERROR , " HY000 " ) ;
RETURN_FALSE ;
}
2005-11-29 04:06:03 +00:00
/* }}} */
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 )
2005-11-29 02:11:39 +00:00
{ NULL , NULL , NULL }
} ;
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 )
{
return 0 ;
}
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 */
2005-11-29 02:11:39 +00:00
pdo_pgsql_get_driver_methods /* get_driver_methods */
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 ;
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 ;
2004-05-20 02:27:49 +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 ) ;
}
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 ) {
2007-06-28 03:13:29 +00:00
spprintf ( & conn_str , 0 , " %s user=%s password=%s connect_timeout=%ld " , dbh - > data_source , dbh - > username , dbh - > password , 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 ) {
2007-06-28 03:13:29 +00:00
spprintf ( & conn_str , 0 , " %s password=%s connect_timeout=%ld " , dbh - > data_source , dbh - > password , 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 ) ;
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 ;
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
*/