2003-03-17 10:54:23 +00:00
< ? php
2007-10-05 14:36:34 +00:00
/**
2005-04-09 12:26:45 +00:00
*
2005-08-17 15:57:50 +00:00
* @ package dbal
2005-04-09 12:26:45 +00:00
* @ version $Id $
2007-10-05 14:36:34 +00:00
* @ copyright ( c ) 2005 phpBB Group
* @ license http :// opensource . org / licenses / gpl - license . php GNU Public License
2005-04-09 12:26:45 +00:00
*
*/
2006-03-19 14:23:21 +00:00
/**
2006-10-14 14:56:46 +00:00
* @ ignore
2006-03-19 14:23:21 +00:00
*/
if ( ! defined ( 'IN_PHPBB' ))
{
exit ;
}
2006-10-14 14:56:46 +00:00
include_once ( $phpbb_root_path . 'includes/db/dbal.' . $phpEx );
2003-03-17 10:54:23 +00:00
2005-04-09 12:26:45 +00:00
/**
* Firebird / Interbase Database Abstraction Layer
2006-10-01 08:48:32 +00:00
* Minimum Requirement is Firebird 2.0
2006-06-13 21:06:29 +00:00
* @ package dbal
2005-04-09 12:26:45 +00:00
*/
2005-08-17 15:57:50 +00:00
class dbal_firebird extends dbal
2003-03-17 10:54:23 +00:00
{
2005-01-09 20:01:20 +00:00
var $last_query_text = '' ;
2006-07-09 16:23:57 +00:00
var $service_handle = false ;
2007-06-16 13:49:49 +00:00
var $affected_rows = 0 ;
2003-03-17 10:54:23 +00:00
2005-10-07 23:00:41 +00:00
/**
* Connect to server
*/
2007-02-19 04:12:13 +00:00
function sql_connect ( $sqlserver , $sqluser , $sqlpassword , $database , $port = false , $persistency = false , $new_link = false )
2005-01-09 20:01:20 +00:00
{
2003-03-17 10:54:23 +00:00
$this -> persistency = $persistency ;
$this -> user = $sqluser ;
2005-01-09 20:01:20 +00:00
$this -> server = $sqlserver . (( $port ) ? ':' . $port : '' );
2008-09-04 12:01:47 +00:00
$this -> dbname = str_replace ( '\\' , '/' , $database );
2003-03-17 10:54:23 +00:00
2008-09-04 12:01:47 +00:00
// There are three possibilities to connect to an interbase db
if ( ! $this -> server )
{
$use_database = $this -> dbname ;
}
else if ( strpos ( $this -> server , '//' ) === 0 )
{
$use_database = $this -> server . $this -> dbname ;
}
else
{
$use_database = $this -> server . ':' . $this -> dbname ;
}
$this -> db_connect_id = ( $this -> persistency ) ? @ ibase_pconnect ( $use_database , $this -> user , $sqlpassword , false , false , 3 ) : @ ibase_connect ( $use_database , $this -> user , $sqlpassword , false , false , 3 );
2003-03-17 10:54:23 +00:00
2008-09-04 12:01:47 +00:00
$this -> service_handle = ( function_exists ( 'ibase_service_attach' ) && $this -> server ) ? @ ibase_service_attach ( $this -> server , $this -> user , $sqlpassword ) : false ;
2006-07-09 16:23:57 +00:00
2003-03-17 10:54:23 +00:00
return ( $this -> db_connect_id ) ? $this -> db_connect_id : $this -> sql_error ( '' );
}
2006-07-09 16:23:57 +00:00
/**
* Version information about used database
2008-09-04 12:01:47 +00:00
* @ param bool $raw if true , only return the fetched sql_server_version
* @ return string sql server version
2006-07-09 16:23:57 +00:00
*/
2008-09-04 12:01:47 +00:00
function sql_server_info ( $raw = false )
2006-07-09 16:23:57 +00:00
{
2006-08-02 17:18:23 +00:00
if ( $this -> service_handle !== false && function_exists ( 'ibase_server_info' ))
2006-07-09 16:23:57 +00:00
{
return @ ibase_server_info ( $this -> service_handle , IBASE_SVC_SERVER_VERSION );
}
2008-09-04 12:01:47 +00:00
return ( $raw ) ? '2.0' : 'Firebird/Interbase' ;
2006-07-09 16:23:57 +00:00
}
2005-10-07 23:00:41 +00:00
/**
2006-06-06 20:53:46 +00:00
* SQL Transaction
2006-08-22 21:26:06 +00:00
* @ access private
2005-10-07 23:00:41 +00:00
*/
2006-06-06 20:53:46 +00:00
function _sql_transaction ( $status = 'begin' )
2003-03-17 10:54:23 +00:00
{
2005-01-09 20:01:20 +00:00
switch ( $status )
2003-03-17 10:54:23 +00:00
{
case 'begin' :
2006-08-02 17:38:48 +00:00
return true ;
2006-06-02 13:26:27 +00:00
break ;
2003-03-17 10:54:23 +00:00
case 'commit' :
2006-06-06 20:53:46 +00:00
return @ ibase_commit ();
2006-06-02 13:26:27 +00:00
break ;
2003-03-17 10:54:23 +00:00
case 'rollback' :
2006-06-06 20:53:46 +00:00
return @ ibase_rollback ();
2006-06-02 13:26:27 +00:00
break ;
2003-03-17 10:54:23 +00:00
}
2006-06-06 20:53:46 +00:00
return true ;
2003-03-17 10:54:23 +00:00
}
2005-10-07 23:00:41 +00:00
/**
* Base query method
2006-08-01 16:14:14 +00:00
*
* @ param string $query Contains the SQL query which shall be executed
* @ param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache
* @ return mixed When casted to bool the returned value returns true on success and false on failure
*
* @ access public
2005-10-07 23:00:41 +00:00
*/
2005-01-09 20:01:20 +00:00
function sql_query ( $query = '' , $cache_ttl = 0 )
2003-03-17 10:54:23 +00:00
{
if ( $query != '' )
{
global $cache ;
2007-01-09 01:33:20 +00:00
// EXPLAIN only in extra debug mode
if ( defined ( 'DEBUG_EXTRA' ))
{
$this -> sql_report ( 'start' , $query );
}
2005-01-09 20:01:20 +00:00
$this -> last_query_text = $query ;
$this -> query_result = ( $cache_ttl && method_exists ( $cache , 'sql_load' )) ? $cache -> sql_load ( $query ) : false ;
2006-05-20 13:20:38 +00:00
$this -> sql_add_num_queries ( $this -> query_result );
2003-03-17 10:54:23 +00:00
2006-10-03 20:38:03 +00:00
if ( $this -> query_result === false )
2005-01-09 20:01:20 +00:00
{
2007-06-16 13:49:49 +00:00
$array = array ();
2007-04-11 02:23:21 +00:00
// We overcome Firebird's 32767 char limit by binding vars
if ( strlen ( $query ) > 32767 )
{
2007-06-16 13:49:49 +00:00
if ( preg_match ( '/^(INSERT INTO[^(]++)\\(([^()]+)\\) VALUES[^(]++\\((.*?)\\)$/s' , $query , $regs ))
2007-04-11 02:23:21 +00:00
{
if ( strlen ( $regs [ 3 ]) > 32767 )
{
2007-07-05 15:45:24 +00:00
preg_match_all ( '/\'(?:[^\']++|\'\')*+\'|[\d-.]+/' , $regs [ 3 ], $vals , PREG_PATTERN_ORDER );
2007-04-11 02:23:21 +00:00
$inserts = $vals [ 0 ];
unset ( $vals );
foreach ( $inserts as $key => $value )
{
if ( ! empty ( $value ) && $value [ 0 ] === " ' " && strlen ( $value ) > 32769 ) // check to see if this thing is greater than the max + 'x2
{
$inserts [ $key ] = '?' ;
$array [] = str_replace ( " '' " , " ' " , substr ( $value , 1 , - 1 ));
}
}
$query = $regs [ 1 ] . '(' . $regs [ 2 ] . ') VALUES (' . implode ( ', ' , $inserts ) . ')' ;
}
}
2007-07-05 15:45:24 +00:00
else if ( preg_match ( '/^(UPDATE ([\\w_]++)\\s+SET )([\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|\\d+)(?:,\\s*[\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+))*+)\\s+(WHERE.*)$/s' , $query , $data ))
2007-04-11 02:23:21 +00:00
{
2007-06-16 13:49:49 +00:00
if ( strlen ( $data [ 3 ]) > 32767 )
2007-04-11 02:23:21 +00:00
{
2007-06-16 13:49:49 +00:00
$update = $data [ 1 ];
$where = $data [ 4 ];
2007-07-05 15:45:24 +00:00
preg_match_all ( '/(\\w++)\\s*=\\s*(\'(?:[^\']++|\'\')*+\'|[\d-.]++)/' , $data [ 3 ], $temp , PREG_SET_ORDER );
2007-04-11 02:23:21 +00:00
unset ( $data );
2007-06-16 13:49:49 +00:00
$cols = array ();
2007-04-11 02:23:21 +00:00
foreach ( $temp as $value )
{
if ( ! empty ( $value [ 2 ]) && $value [ 2 ][ 0 ] === " ' " && strlen ( $value [ 2 ]) > 32769 ) // check to see if this thing is greater than the max + 'x2
{
$array [] = str_replace ( " '' " , " ' " , substr ( $value [ 2 ], 1 , - 1 ));
2007-06-16 13:49:49 +00:00
$cols [] = $value [ 1 ] . '=?' ;
2007-04-11 02:23:21 +00:00
}
else
{
2007-06-16 13:49:49 +00:00
$cols [] = $value [ 1 ] . '=' . $value [ 2 ];
2007-04-11 02:23:21 +00:00
}
}
2007-06-16 13:49:49 +00:00
$query = $update . implode ( ', ' , $cols ) . ' ' . $where ;
unset ( $cols );
2007-04-11 02:23:21 +00:00
}
}
}
2007-08-24 18:09:59 +00:00
if ( ! function_exists ( 'ibase_affected_rows' ) && ( preg_match ( '/^UPDATE ([\w_]++)\s+SET [\w_]++\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+)(?:,\s*[\w_]++\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+))*+\s+(WHERE.*)?$/s' , $query , $regs ) || preg_match ( '/^DELETE FROM ([\w_]++)\s*(WHERE\s*.*)?$/s' , $query , $regs )))
2007-06-16 13:49:49 +00:00
{
2007-08-24 18:09:59 +00:00
$affected_sql = 'SELECT COUNT(*) as num_rows_affected FROM ' . $regs [ 1 ];
if ( ! empty ( $regs [ 2 ]))
{
$affected_sql .= ' ' . $regs [ 2 ];
}
2007-06-16 13:49:49 +00:00
if ( ! ( $temp_q_id = @ ibase_query ( $this -> db_connect_id , $affected_sql )))
{
return false ;
}
$temp_result = @ ibase_fetch_assoc ( $temp_q_id );
@ ibase_free_result ( $temp_q_id );
$this -> affected_rows = ( $temp_result ) ? $temp_result [ 'NUM_ROWS_AFFECTED' ] : false ;
}
if ( sizeof ( $array ))
2007-04-11 02:23:21 +00:00
{
2007-06-16 13:49:49 +00:00
$p_query = @ ibase_prepare ( $this -> db_connect_id , $query );
2007-04-11 02:23:21 +00:00
array_unshift ( $array , $p_query );
$this -> query_result = call_user_func_array ( 'ibase_execute' , $array );
unset ( $array );
if ( $this -> query_result === false )
{
$this -> sql_error ( $query );
}
}
else if (( $this -> query_result = @ ibase_query ( $this -> db_connect_id , $query )) === false )
2003-03-17 10:54:23 +00:00
{
$this -> sql_error ( $query );
}
2007-01-09 01:33:20 +00:00
if ( defined ( 'DEBUG_EXTRA' ))
{
$this -> sql_report ( 'stop' , $query );
}
2006-08-02 17:38:48 +00:00
if ( ! $this -> transaction )
{
if ( function_exists ( 'ibase_commit_ret' ))
{
@ ibase_commit_ret ();
}
else
{
2006-10-01 08:48:32 +00:00
// way cooler than ibase_commit_ret :D
@ ibase_query ( 'COMMIT RETAIN;' );
2006-08-02 17:38:48 +00:00
}
}
2005-01-09 20:01:20 +00:00
if ( $cache_ttl && method_exists ( $cache , 'sql_save' ))
2003-03-17 10:54:23 +00:00
{
2005-10-07 23:00:41 +00:00
$this -> open_queries [( int ) $this -> query_result ] = $this -> query_result ;
2005-01-09 20:01:20 +00:00
$cache -> sql_save ( $query , $this -> query_result , $cache_ttl );
2003-03-17 10:54:23 +00:00
}
2006-03-17 12:51:32 +00:00
else if ( strpos ( $query , 'SELECT' ) === 0 && $this -> query_result )
2005-10-07 23:00:41 +00:00
{
$this -> open_queries [( int ) $this -> query_result ] = $this -> query_result ;
}
2003-03-17 10:54:23 +00:00
}
2007-01-09 01:33:20 +00:00
else if ( defined ( 'DEBUG_EXTRA' ))
{
$this -> sql_report ( 'fromcache' , $query );
}
2003-03-17 10:54:23 +00:00
}
else
{
return false ;
}
2008-09-02 13:27:37 +00:00
return $this -> query_result ;
2003-03-17 10:54:23 +00:00
}
2005-10-07 23:00:41 +00:00
/**
* Build LIMIT query
*/
2007-01-17 18:41:49 +00:00
function _sql_query_limit ( $query , $total , $offset = 0 , $cache_ttl = 0 )
2006-06-02 13:26:27 +00:00
{
2007-01-17 18:41:49 +00:00
$this -> query_result = false ;
2003-03-17 10:54:23 +00:00
2007-01-17 18:41:49 +00:00
$query = 'SELECT FIRST ' . $total . (( ! empty ( $offset )) ? ' SKIP ' . $offset : '' ) . substr ( $query , 6 );
2003-03-17 10:54:23 +00:00
2007-10-05 14:36:34 +00:00
return $this -> sql_query ( $query , $cache_ttl );
2003-03-17 10:54:23 +00:00
}
2005-10-07 23:00:41 +00:00
/**
* Return number of affected rows
*/
2003-03-17 10:54:23 +00:00
function sql_affectedrows ()
{
2005-10-07 23:00:41 +00:00
// PHP 5+ function
if ( function_exists ( 'ibase_affected_rows' ))
{
2006-04-19 05:20:18 +00:00
return ( $this -> db_connect_id ) ? @ ibase_affected_rows ( $this -> db_connect_id ) : false ;
2005-10-07 23:00:41 +00:00
}
else
{
2007-06-16 13:49:49 +00:00
return $this -> affected_rows ;
2005-10-07 23:00:41 +00:00
}
2003-03-17 10:54:23 +00:00
}
2005-10-07 23:00:41 +00:00
/**
* Fetch current row
*/
2005-01-09 20:01:20 +00:00
function sql_fetchrow ( $query_id = false )
2003-03-17 10:54:23 +00:00
{
global $cache ;
2006-10-04 15:15:40 +00:00
if ( $query_id === false )
2003-03-17 10:54:23 +00:00
{
$query_id = $this -> query_result ;
}
2005-01-09 20:01:20 +00:00
if ( isset ( $cache -> sql_rowset [ $query_id ]))
2003-03-17 10:54:23 +00:00
{
return $cache -> sql_fetchrow ( $query_id );
}
2006-10-04 15:15:40 +00:00
if ( $query_id === false )
{
return false ;
}
2003-03-20 01:32:57 +00:00
$row = array ();
2005-01-09 20:01:20 +00:00
$cur_row = @ ibase_fetch_object ( $query_id , IBASE_TEXT );
if ( ! $cur_row )
{
return false ;
}
foreach ( get_object_vars ( $cur_row ) as $key => $value )
2003-03-20 01:32:57 +00:00
{
2007-08-24 18:00:28 +00:00
$row [ strtolower ( $key )] = ( is_string ( $value )) ? trim ( str_replace ( array ( " \\ 0 " , " \\ n " ), array ( " \0 " , " \n " ), $value )) : $value ;
2003-03-20 01:32:57 +00:00
}
2005-10-07 23:00:41 +00:00
return ( sizeof ( $row )) ? $row : false ;
2003-03-17 10:54:23 +00:00
}
2005-10-07 23:00:41 +00:00
/**
2006-10-04 15:15:40 +00:00
* Seek to given row number
* rownum is zero - based
2005-10-07 23:00:41 +00:00
*/
2007-06-12 21:24:22 +00:00
function sql_rowseek ( $rownum , & $query_id )
2003-03-17 10:54:23 +00:00
{
2006-08-01 16:14:14 +00:00
global $cache ;
2006-10-04 15:15:40 +00:00
if ( $query_id === false )
2003-03-17 10:54:23 +00:00
{
$query_id = $this -> query_result ;
}
2003-03-20 01:32:57 +00:00
2006-10-04 15:15:40 +00:00
if ( isset ( $cache -> sql_rowset [ $query_id ]))
2003-03-17 10:54:23 +00:00
{
2006-10-04 15:15:40 +00:00
return $cache -> sql_rowseek ( $rownum , $query_id );
2003-03-17 10:54:23 +00:00
}
2005-10-07 23:00:41 +00:00
2006-10-04 15:15:40 +00:00
if ( $query_id === false )
2003-03-17 10:54:23 +00:00
{
2006-10-04 15:15:40 +00:00
return ;
2003-03-17 10:54:23 +00:00
}
2003-03-17 23:06:10 +00:00
2006-10-04 15:15:40 +00:00
$this -> sql_freeresult ( $query_id );
$query_id = $this -> sql_query ( $this -> last_query_text );
if ( $query_id === false )
2006-08-01 16:14:14 +00:00
{
2006-10-04 15:15:40 +00:00
return false ;
2006-08-01 16:14:14 +00:00
}
2005-10-07 23:00:41 +00:00
// We do not fetch the row for rownum == 0 because then the next resultset would be the second row
for ( $i = 0 ; $i < $rownum ; $i ++ )
2003-03-17 23:06:10 +00:00
{
if ( ! $this -> sql_fetchrow ( $query_id ))
{
return false ;
}
}
return true ;
2003-03-17 10:54:23 +00:00
}
2005-10-07 23:00:41 +00:00
/**
* Get last inserted id after insert statement
*/
2003-03-17 10:54:23 +00:00
function sql_nextid ()
{
2005-10-07 23:00:41 +00:00
$query_id = $this -> query_result ;
2006-10-04 15:15:40 +00:00
if ( $query_id !== false && $this -> last_query_text != '' )
2003-03-17 10:54:23 +00:00
{
2007-02-19 04:12:13 +00:00
if ( $this -> query_result && preg_match ( '#^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)#i' , $this -> last_query_text , $tablename ))
2003-03-17 23:06:10 +00:00
{
2007-02-19 04:12:13 +00:00
$sql = 'SELECT GEN_ID(' . $tablename [ 1 ] . '_gen, 0) AS new_id FROM RDB$DATABASE' ;
2006-06-02 13:26:27 +00:00
2007-01-26 16:09:51 +00:00
if ( ! ( $temp_q_id = @ ibase_query ( $this -> db_connect_id , $sql )))
2005-10-07 23:00:41 +00:00
{
return false ;
}
2003-03-17 10:54:23 +00:00
2007-02-19 04:12:13 +00:00
$temp_result = @ ibase_fetch_assoc ( $temp_q_id );
2005-10-07 23:00:41 +00:00
@ ibase_free_result ( $temp_q_id );
2003-03-17 10:54:23 +00:00
2007-02-19 04:12:13 +00:00
return ( $temp_result ) ? $temp_result [ 'NEW_ID' ] : false ;
2005-10-07 23:00:41 +00:00
}
2003-03-17 23:06:10 +00:00
}
2006-06-02 13:26:27 +00:00
2005-10-07 23:00:41 +00:00
return false ;
2003-03-17 10:54:23 +00:00
}
2005-10-07 23:00:41 +00:00
/**
* Free sql result
*/
2003-03-17 10:54:23 +00:00
function sql_freeresult ( $query_id = false )
{
2006-08-01 16:14:14 +00:00
global $cache ;
2006-10-04 15:15:40 +00:00
if ( $query_id === false )
2003-03-17 10:54:23 +00:00
{
$query_id = $this -> query_result ;
}
2006-08-01 16:14:14 +00:00
if ( isset ( $cache -> sql_rowset [ $query_id ]))
{
return $cache -> sql_freeresult ( $query_id );
}
2005-10-07 23:00:41 +00:00
if ( isset ( $this -> open_queries [( int ) $query_id ]))
{
unset ( $this -> open_queries [( int ) $query_id ]);
return @ ibase_free_result ( $query_id );
2005-01-09 20:01:20 +00:00
}
2005-10-07 23:00:41 +00:00
return false ;
2003-03-17 10:54:23 +00:00
}
2005-10-07 23:00:41 +00:00
/**
* Escape string used in sql query
*/
2003-03-17 10:54:23 +00:00
function sql_escape ( $msg )
{
2008-10-02 12:04:12 +00:00
return str_replace ( array ( " ' " , " \0 " ), array ( " '' " , '' ), $msg );
2003-03-17 10:54:23 +00:00
}
2007-06-24 12:49:13 +00:00
/**
* Build LIKE expression
* @ access private
*/
function _sql_like_expression ( $expression )
{
2007-06-24 15:34:46 +00:00
return $expression . " ESCAPE ' \\ ' " ;
2007-06-24 12:49:13 +00:00
}
2006-05-05 22:06:17 +00:00
/**
* Build db - specific query data
2006-08-22 21:26:06 +00:00
* @ access private
2006-05-05 22:06:17 +00:00
*/
function _sql_custom_build ( $stage , $data )
{
return $data ;
}
2005-10-07 23:00:41 +00:00
/**
* return sql error array
2006-08-22 21:26:06 +00:00
* @ access private
2005-10-07 23:00:41 +00:00
*/
function _sql_error ()
2003-03-17 10:54:23 +00:00
{
2005-08-17 15:57:50 +00:00
return array (
'message' => @ ibase_errmsg (),
2006-04-18 04:17:53 +00:00
'code' => ( @ function_exists ( 'ibase_errcode' ) ? @ ibase_errcode () : '' )
2005-08-17 15:57:50 +00:00
);
2003-03-17 10:54:23 +00:00
}
2005-10-07 23:00:41 +00:00
/**
* Close sql connection
2006-08-22 21:26:06 +00:00
* @ access private
2005-10-07 23:00:41 +00:00
*/
function _sql_close ()
2005-04-22 17:44:36 +00:00
{
2006-07-09 16:23:57 +00:00
if ( $this -> service_handle !== false )
{
@ ibase_service_detach ( $this -> service_handle );
}
2005-10-07 23:00:41 +00:00
return @ ibase_close ( $this -> db_connect_id );
}
2005-04-22 17:44:36 +00:00
2005-10-07 23:00:41 +00:00
/**
* Build db - specific report
2006-08-22 21:26:06 +00:00
* @ access private
2005-10-07 23:00:41 +00:00
*/
function _sql_report ( $mode , $query = '' )
{
2005-04-22 17:44:36 +00:00
switch ( $mode )
{
case 'start' :
2005-10-07 23:00:41 +00:00
break ;
2005-04-22 17:44:36 +00:00
case 'fromcache' :
$endtime = explode ( ' ' , microtime ());
$endtime = $endtime [ 0 ] + $endtime [ 1 ];
$result = @ ibase_query ( $this -> db_connect_id , $query );
while ( $void = @ ibase_fetch_object ( $result , IBASE_TEXT ))
{
// Take the time spent on parsing rows into account
}
2006-05-05 22:06:17 +00:00
@ ibase_free_result ( $result );
2005-10-07 23:00:41 +00:00
2005-04-22 17:44:36 +00:00
$splittime = explode ( ' ' , microtime ());
$splittime = $splittime [ 0 ] + $splittime [ 1 ];
2005-10-07 23:00:41 +00:00
$this -> sql_report ( 'record_fromcache' , $query , $endtime , $splittime );
2005-04-22 17:44:36 +00:00
2005-10-07 23:00:41 +00:00
break ;
2005-04-22 17:44:36 +00:00
}
}
2005-08-17 15:57:50 +00:00
}
2003-03-17 10:54:23 +00:00
?>