eZ Publish  [trunk]
ezdbinterface.php
Go to the documentation of this file.
00001 <?php
00002 /**
00003  * File containing the eZDBInterface class.
00004  *
00005  * @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved.
00006  * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2
00007  * @version //autogentag//
00008  * @package lib
00009  */
00010 
00011 /**
00012  * The eZDBInterface defines the interface for all database implementations
00013  *
00014  * @todo Convert methods and variables marked as protected/private to protected/private methods and variables
00015  *
00016  * @package lib
00017  * @subpackage eZDB
00018  */
00019 class eZDBInterface
00020 {
00021     const BINDING_NO = 0;
00022     const BINDING_NAME = 1;
00023     const BINDING_ORDERED = 2;
00024 
00025     const RELATION_TABLE = 0;
00026     const RELATION_SEQUENCE = 1;
00027     const RELATION_TRIGGER = 2;
00028     const RELATION_VIEW = 3;
00029     const RELATION_INDEX = 4;
00030 
00031     const RELATION_TABLE_BIT = 1;
00032     const RELATION_SEQUENCE_BIT = 2;
00033     const RELATION_TRIGGER_BIT = 4;
00034     const RELATION_VIEW_BIT = 8;
00035     const RELATION_INDEX_BIT = 16;
00036 
00037     const RELATION_NONE = 0;
00038     const RELATION_MASK = 31;
00039 
00040     const ERROR_MISSING_EXTENSION = 1;
00041 
00042     const SERVER_MASTER = 1;
00043     const SERVER_SLAVE = 2;
00044 
00045     /**
00046      * Creates a new eZDBInterface object and connects to the database backend.
00047      *
00048      * @param array $parameters
00049      */
00050     function eZDBInterface( $parameters )
00051     {
00052         $server = $parameters['server'];
00053         $port = $parameters['port'];
00054         $user = $parameters['user'];
00055         $password = $parameters['password'];
00056         $db = $parameters['database'];
00057         $useSlaveServer = $parameters['use_slave_server'];
00058         $slaveServer = $parameters['slave_server'];
00059         $slavePort = $parameters['slave_port'];
00060         $slaveUser = $parameters['slave_user'];
00061         $slavePassword = $parameters['slave_password'];
00062         $slaveDB =  $parameters['slave_database'];
00063         $socketPath = $parameters['socket'];
00064         $charset = $parameters['charset'];
00065         $isInternalCharset = $parameters['is_internal_charset'];
00066         $builtinEncoding = $parameters['builtin_encoding'];
00067         $connectRetries = $parameters['connect_retries'];
00068 
00069         if ( $parameters['use_persistent_connection'] == 'enabled' )
00070         {
00071             $this->UsePersistentConnection = true;
00072         }
00073 
00074         $this->DB = $db;
00075         $this->Server = $server;
00076         $this->Port = $port;
00077         $this->SocketPath = $socketPath;
00078         $this->User = $user;
00079         $this->Password = $password;
00080         $this->UseSlaveServer = $useSlaveServer;
00081         $this->SlaveDB = $slaveDB;
00082         $this->SlaveServer = $slaveServer;
00083         $this->SlavePort = $slavePort;
00084         $this->SlaveUser = $slaveUser;
00085         $this->SlavePassword = $slavePassword;
00086         $this->Charset = $charset;
00087         $this->IsInternalCharset = $isInternalCharset;
00088         $this->UseBuiltinEncoding = $builtinEncoding;
00089         $this->ConnectRetries = $connectRetries;
00090         $this->DBConnection = false;
00091         $this->DBWriteConnection = false;
00092         $this->TransactionCounter = 0;
00093         $this->TransactionIsValid = false;
00094         $this->TransactionStackTree = false;
00095 
00096         $this->OutputTextCodec = null;
00097         $this->InputTextCodec = null;
00098 
00099         $tmpOutputTextCodec = eZTextCodec::instance( $charset, false, false );
00100         $tmpInputTextCodec = eZTextCodec::instance( false, $charset, false );
00101         unset( $this->OutputTextCodec );
00102         unset( $this->InputTextCodec );
00103         $this->OutputTextCodec = null;
00104         $this->InputTextCodec = null;
00105 
00106         if ( $tmpOutputTextCodec && $tmpInputTextCodec )
00107         {
00108             if ( $tmpOutputTextCodec->conversionRequired() && $tmpInputTextCodec->conversionRequired() )
00109             {
00110                 $this->OutputTextCodec =& $tmpOutputTextCodec;
00111                 $this->InputTextCodec =& $tmpInputTextCodec;
00112             }        
00113         }
00114 
00115         $this->OutputSQL = false;
00116         $this->SlowSQLTimeout = 0;
00117         $ini = eZINI::instance();
00118         if ( ( $ini->variable( "DatabaseSettings", "SQLOutput" ) == "enabled" ) and
00119              ( $ini->variable( "DebugSettings", "DebugOutput" ) == "enabled" ) )
00120         {
00121             $this->OutputSQL = true;
00122 
00123             $this->SlowSQLTimeout = (int) $ini->variable( "DatabaseSettings", "SlowQueriesOutput" );
00124         }
00125         if ( $ini->variable( "DatabaseSettings", "DebugTransactions" ) == "enabled" )
00126         {
00127             // Setting it to an array turns on the debugging
00128             $this->TransactionStackTree = array();
00129         }
00130 
00131         $this->QueryAnalysisOutput = false;
00132         if ( $ini->variable( "DatabaseSettings", "QueryAnalysisOutput" ) == "enabled" )
00133         {
00134             $this->QueryAnalysisOutput = true;
00135         }
00136 
00137         $this->IsConnected = false;
00138         $this->NumQueries = 0;
00139         $this->StartTime = false;
00140         $this->EndTime = false;
00141         $this->TimeTaken = false;
00142 
00143         $this->AttributeVariableMap =
00144         array(
00145             'database_name' => 'DB',
00146             'database_server' => 'Server',
00147             'database_port' => 'Port',
00148             'database_socket_path' => 'SocketPath',
00149             'database_user' => 'User',
00150             'use_slave_server' => 'UseSlaveServer',
00151             'slave_database_name' => 'SlaveDB',
00152             'slave_database_server' => 'SlaveServer',
00153             'slave_database_port' => 'SlavePort',
00154             'slave_database_user' => 'SlaveUser',
00155             'charset' => 'Charset',
00156             'is_internal_charset' => 'IsInternalCharset',
00157             'use_builting_encoding' => 'UseBuiltinEncoding',
00158             'retry_count' => 'ConnectRetries' );
00159     }
00160 
00161     /**
00162      * Returns the available attributes for this database handler.
00163      *
00164      * @return array
00165      */
00166     function attributes()
00167     {
00168         return array_keys( $this->AttributeVariableMap );
00169     }
00170 
00171     /**
00172      * Returns true if the attribute $name exists for this database handler.
00173      *
00174      * @param string $name
00175      * @return bool
00176      */
00177     function hasAttribute( $name )
00178     {
00179         if ( isset( $this->AttributeVariableMap[$name] ) )
00180         {
00181             return true;
00182         }
00183         return false;
00184     }
00185 
00186     /**
00187      * Returns the value of the attribute $name if it exists, otherwise null.
00188      *
00189      * @param string $name
00190      * @return null
00191      */
00192     function attribute( $name )
00193     {
00194         if ( isset( $this->AttributeVariableMap[$name] ) )
00195         {
00196             $memberVariable = $this->AttributeVariableMap[$name];
00197             return $this->$memberVariable;
00198         }
00199         else
00200         {
00201             eZDebug::writeError( "Attribute '$name' does not exist", __METHOD__ );
00202             return null;
00203         }
00204     }
00205 
00206     /**
00207      * Checks if the requested character set matches the one used in the database.
00208      *
00209      * The default is to always return true, see the specific database handler for more information.
00210      *
00211      * @param string|array $charset
00212      * @param string $currentCharset The charset that the database uses, will only be set if the match fails.
00213      * @return bool true if it matches or false if it differs.
00214      */
00215     function checkCharset( $charset, &$currentCharset )
00216     {
00217         return true;
00218     }
00219 
00220     /**
00221      * Prepare the sql file so we can create the database.
00222      *
00223      * @access private
00224      * @param resource $fd The file descriptor
00225      * @param string $buffer Reference to string buffer for SQL queries.
00226      * @return array
00227      */
00228     function prepareSqlQuery( &$fd, &$buffer )
00229     {
00230 
00231         $sqlQueryArray = array();
00232         while( count( $sqlQueryArray ) == 0 && !feof( $fd ) )
00233         {
00234             $buffer  .= fread( $fd, 4096 );
00235             if ( $buffer )
00236             {
00237                 // Fix SQL file by deleting all comments and newlines
00238                 // eZDebug::writeDebug( $buffer, "read data" );
00239                 $sqlQuery = preg_replace( array( "/^#.*\n" . "/m",
00240                                                  "#^/\*.*\*/\n" . "#m",
00241                                                  "/^--.*\n" . "/m",
00242                                                  "/\n|\r\n|\r/m" ),
00243                                           array( "",
00244                                                  "",
00245                                                  "",
00246                                                  "\n" ),
00247                                           $buffer );
00248 //            eZDebug::writeDebug( $sqlQuery, "read data" );
00249 
00250                 // Split the query into an array
00251                 $sqlQueryArray = preg_split( "/;\n/m", $sqlQuery );
00252 
00253                 if ( preg_match( '/;\n/m', $sqlQueryArray[ count( $sqlQueryArray ) -1 ] ) )
00254                 {
00255                     $buffer = '';
00256                 }
00257                 else
00258                 {
00259                     $buffer = $sqlQueryArray[ count( $sqlQueryArray ) -1 ];
00260                     array_splice( $sqlQueryArray, count( $sqlQueryArray ) -1 , 1 );
00261                 }
00262             }
00263             else
00264             {
00265                 return $sqlQueryArray;
00266 
00267             }
00268         }
00269         return $sqlQueryArray;
00270     }
00271 
00272     /**
00273      * Inserts the SQL file $sqlFile found in the path $path into the currently connected database.
00274      *
00275      * @param string $path
00276      * @param string $sqlFile
00277      * @param bool $usePathType
00278      * @return bool true if succesful.
00279      */
00280     function insertFile( $path, $sqlFile, $usePathType = true )
00281     {
00282         $type = $this->databaseName();
00283 
00284         if ( $usePathType )
00285             $sqlFileName = eZDir::path( array( $path, $type, $sqlFile ) );
00286         else
00287             $sqlFileName = eZDir::path( array( $path, $sqlFile ) );
00288         if ( !file_exists( $sqlFileName ) )
00289         {
00290             eZDebug::writeError( "File not found: $sqlFileName", __METHOD__ );
00291             return false;
00292         }
00293         $sqlFileHandler = fopen( $sqlFileName, 'rb' );
00294         $buffer = '';
00295         $done = false;
00296         while ( count( ( $sqlArray = $this->prepareSqlQuery( $sqlFileHandler, $buffer ) ) ) > 0 )
00297         {
00298             // Turn unneccessary SQL debug output off
00299             $oldOutputSQL = $this->OutputSQL;
00300             $this->OutputSQL = false;
00301             if ( $sqlArray && is_array( $sqlArray ) )
00302             {
00303                 $done = true;
00304                 foreach( $sqlArray as $singleQuery )
00305                 {
00306                     $singleQuery = preg_replace( "/\n|\r\n|\r/", " ", $singleQuery );
00307                     if ( preg_match( "#^ */(.+)$#", $singleQuery, $matches ) )
00308                     {
00309                         $singleQuery = $matches[1];
00310                     }
00311                     if ( trim( $singleQuery ) != "" )
00312                     {
00313 //                    eZDebug::writeDebug( $singleQuery );
00314                         $this->query( trim( $singleQuery ) );
00315                         if ( $this->errorNumber() )
00316                         {
00317                             return false;
00318                         }
00319                     }
00320                 }
00321 
00322             }
00323             $this->OutputSQL = $oldOutputSQL;
00324         }
00325         return $done;
00326 
00327     }
00328 
00329     /**
00330      * Writes a debug notice with query information.
00331      *
00332      * @access private
00333      * @param string $class
00334      * @param string $sql
00335      * @param int|string $numRows
00336      * @param int|string $timeTaken
00337      * @param bool $asDebug
00338      */
00339     function reportQuery( $class, $sql, $numRows, $timeTaken, $asDebug = false )
00340     {
00341         $rowText = '';
00342         if ( $numRows !== false ) $rowText = "$numRows rows, ";
00343 
00344         $backgroundClass = ($this->TransactionCounter > 0  ? "debugtransaction transactionlevel-$this->TransactionCounter" : '');
00345         if ( $asDebug )
00346             eZDebug::writeDebug( "$sql", "$class::query($rowText" . number_format( $timeTaken, 3 ) . ' ms) query number per page:' . $this->NumQueries++, $backgroundClass );
00347         else
00348             eZDebug::writeNotice( "$sql", "$class::query($rowText" . number_format( $timeTaken, 3 ) . ' ms) query number per page:' . $this->NumQueries++, $backgroundClass );
00349     }
00350 
00351     /**
00352      * Enabled or disables sql output.
00353      *
00354      * @param bool $enabled
00355      */
00356     function setIsSQLOutputEnabled( $enabled )
00357     {
00358         $this->OutputSQL = $enabled;
00359     }
00360 
00361     /**
00362      * Records the current micro time. End the timer with endTimer() and fetch the result with timeTaken();
00363      *
00364      * @access private
00365      */
00366     function startTimer()
00367     {
00368         $this->StartTime = microtime( true );
00369     }
00370 
00371     /**
00372      * Stops the current timer and calculates the time taken.
00373      *
00374      * @access private
00375      */
00376     function endTimer()
00377     {
00378         $this->EndTime = microtime( true );
00379         // Calculate time taken in ms
00380         $this->TimeTaken = $this->EndTime - $this->StartTime;
00381         $this->TimeTaken *= 1000.0;
00382     }
00383 
00384     /**
00385      * Returns the micro time when the timer was start or false if no timer.
00386      *
00387      * @access private
00388      * @return bool|float
00389      */
00390     function startTime()
00391     {
00392         return $this->StartTime;
00393     }
00394 
00395     /**
00396      * Returns the micro time when the timer was ended or false if no timer.
00397      *
00398      * @access private
00399      * @return bool|float
00400      */
00401     function endTime()
00402     {
00403         return $this->EndTime;
00404     }
00405 
00406     /**
00407      * Returns the number of milliseconds the last operation took or false if no value.
00408      *
00409      * @access private
00410      * @return bool|float
00411      */
00412     function timeTaken()
00413     {
00414         return $this->TimeTaken;
00415     }
00416 
00417     /**
00418      * Returns the name of driver, this is used to determine the name of the database type.
00419      *
00420      * For instance multiple implementations of the MySQL database will all return 'mysql'.
00421      *
00422      * @return string
00423      */
00424     function databaseName()
00425     {
00426         return '';
00427     }
00428 
00429     /**
00430      * Returns the socket path for the database or false if no socket path was defined.
00431      *
00432      * @return string|bool
00433      */
00434     function socketPath()
00435     {
00436         return $this->SocketPath;
00437     }
00438 
00439     /**
00440      * Returns the number of times the db handler should try to reconnect if it fails.
00441      *
00442      * @return int
00443      */
00444     function connectRetryCount()
00445     {
00446         return $this->ConnectRetries;
00447     }
00448 
00449     /**
00450      * Returns the number of seconds the db handler should wait before rereconnecting.
00451      *
00452      * @return int
00453      */
00454     function connectRetryWaitTime()
00455     {
00456         return 3;
00457     }
00458 
00459     /**
00460      * Returns a mask of the relation type it supports.
00461      *
00462      * @return int
00463      */
00464     function supportedRelationTypeMask()
00465     {
00466         return eZDBInterface::RELATION_NONE;
00467     }
00468 
00469     /**
00470      * Returns if the short column names should be used insted of default ones
00471      *
00472      * @return bool
00473      */
00474     function useShortNames()
00475     {
00476         return false;
00477     }
00478 
00479     /**
00480      * Returns an array of the relation types.
00481      * @return array
00482      */
00483     function supportedRelationTypes()
00484     {
00485         return array();
00486     }
00487 
00488     /**
00489      * Returns a sql-expression(string) to get substring.
00490      *
00491      * @param string $string
00492      * @param int $from
00493      * @param int $len
00494      * @return string
00495      */
00496     function subString( $string, $from, $len = null )
00497     {
00498         return '';
00499     }
00500 
00501     /**
00502      * Returns a sql-expression(string) to concatenate strings.
00503      *
00504      * @param array $strings
00505      * @return string
00506      */
00507     function concatString( $strings = array() )
00508     {
00509         return '';
00510     }
00511 
00512     /**
00513      * Returns a sql-expression(string) to generate a md5 sum of the string.
00514      *
00515      * @param string $str
00516      * @return string
00517      */
00518     function md5( $str )
00519     {
00520         return '';
00521     }
00522 
00523     /**
00524      * Returns a sql-expression(string) to generate a bit and  of the argument.
00525      *
00526      * @param string $arg1
00527      * @param string $arg2
00528      * @return string
00529      */
00530     function bitAnd( $arg1, $arg2 )
00531     {
00532         return '(' . $arg1 . ' & ' . $arg2 . ' ) ';
00533     }
00534 
00535     /**
00536      * Returns a sql-expression(string) to generate a bit and  of the argument.
00537      *
00538      * @param string $arg1
00539      * @param string $arg2
00540      * @return string
00541      */
00542     function bitOr( $arg1, $arg2 )
00543     {
00544         return '( ' . $arg1 . ' | ' . $arg2 . ' ) ';
00545     }
00546 
00547     /**
00548      * Checks if the version number of the server is equal or larger than $minVersion.
00549      *
00550      * Will also check if the database type is correct if $name is set.
00551      *
00552      * @param string $minVersion A string denoting the min. required version.
00553      * @param string|bool $name The name of the database type it requires or false if it does not matter.
00554      * @return bool true if the server fulfills the requirements.
00555      */
00556     function hasRequiredServerVersion( $minVersion, $name = false )
00557     {
00558         if ( $name !== false and
00559              $name != $this->databaseName() )
00560             return false;
00561 
00562         $version = $this->databaseServerVersion();
00563         $version = $version['string'];
00564         return version_compare( $version, $minVersion ) >= 0;
00565     }
00566 
00567     /**
00568      * Returns the version of the database server or false if no version could be retrieved/
00569      *
00570      * @return string|bool
00571      */
00572     function databaseServerVersion()
00573     {
00574     }
00575 
00576     /**
00577      * Returns the version of the database client or false if no version could be retrieved/
00578      *
00579      * @return string|bool
00580      */
00581     function databaseClientVersion()
00582     {
00583     }
00584 
00585     /**
00586      * Returns true if the charset $charset is supported by the connected database.
00587      *
00588      * @param string $charset
00589      * @return bool
00590      */
00591     function isCharsetSupported( $charset )
00592     {
00593         return false;
00594     }
00595 
00596     /**
00597      * Returns the charset which the database is encoded in.
00598      *
00599      * @see usesBuiltinEncoding()
00600      * @return string
00601      */
00602     function charset()
00603     {
00604         return $this->Charset;
00605     }
00606 
00607     /**
00608      * Returns true if the database handles encoding itself. If not, all queries and returned data must be decoded yourselves.
00609      *
00610      * This functionality might be removed in the future
00611      *
00612      * @return bool
00613      */
00614     function usesBuiltinEncoding()
00615     {
00616         return $this->UseBuiltinEncoding;
00617     }
00618 
00619     /**
00620      * Returns type of binding used in database plugin.
00621      *
00622      * @return int
00623      */
00624     function bindingType()
00625     {
00626     }
00627 
00628     /**
00629      * Binds variable.
00630      *
00631      * @param mixed $value
00632      * @param mixed $fieldDef
00633      * @return mixed
00634      */
00635     function bindVariable( $value, $fieldDef = false )
00636     {
00637     }
00638 
00639     /**
00640      * Execute a query on the global MySQL database link.  If it returns an error, the script is halted and the
00641      * attempted SQL query and MySQL error message are printed.
00642      *
00643      * @param string $sql SQL query to execute.
00644      * @param int|bool $server
00645      * @return mixed
00646      */
00647     function query( $sql, $server = false )
00648     {
00649     }
00650 
00651     /**
00652      * Executes an SQL query and returns the result as an array of accociative arrays.
00653      *
00654      * Example:
00655      * <code>
00656      * $db->arrayQuery( 'SELECT * FROM eztable', array( 'limit' => 10, 'offset' => 5 ) );
00657      * </code>
00658      *
00659      * @param string $sql SQL query to execute.
00660      * @param array $params Associative array containing extra parameters, can contain:
00661      *                      - offset -> The offset of the query.
00662      *                      - limit -> The limit of the query.
00663      *                      - column - Limit returned row arrays to only contain this column.
00664      * @param int|bool $server Which server to execute the query on, either eZDBInterface::SERVER_MASTER or eZDBInterface::SERVER_SLAVE
00665      * @return array
00666      */
00667     function arrayQuery( $sql, $params = array(), $server = false )
00668     {
00669     }
00670 
00671     /**
00672      * Locks one or several tables
00673      *
00674      * @param string|array $table
00675      */
00676     function lock( $table )
00677     {
00678     }
00679 
00680     /**
00681      * Releases table locks.
00682      *
00683      * @return void
00684      */
00685     function unlock()
00686     {
00687     }
00688 
00689     /**
00690      * Begin a new transaction.
00691      *
00692      * If we are already in transaction then we omit this new transaction and its matching commit or rollback.
00693      *
00694      * @return bool
00695      */
00696     function begin()
00697     {
00698         $ini = eZINI::instance();
00699         if ($ini->variable( "DatabaseSettings", "Transactions" ) == "enabled")
00700         {
00701             if ( $this->TransactionCounter > 0 )
00702             {
00703                 if ( is_array( $this->TransactionStackTree ) )
00704                 {
00705                     // Make a new sub-level for debugging
00706                     $bt = debug_backtrace();
00707                     $subLevels =& $this->TransactionStackTree['sub_levels'];
00708                     for ( $i = 1; $i < $this->TransactionCounter; ++$i )
00709                     {
00710                         $subLevels =& $subLevels[count( $subLevels ) - 1]['sub_levels'];
00711                     }
00712                     // Next entry will be at the end
00713                     $subLevels[count( $subLevels )] = array( 'level' => $this->TransactionCounter,
00714                                                              'trace' => $bt,
00715                                                              'sub_levels' => array() );
00716                 }
00717                 ++$this->TransactionCounter;
00718                 return false;
00719             }
00720             else
00721             {
00722                 if ( is_array( $this->TransactionStackTree ) )
00723                 {
00724                     // Start new stack tree for debugging
00725                     $bt = debug_backtrace();
00726                     $this->TransactionStackTree = array( 'level' => $this->TransactionCounter,
00727                                                          'trace' => $bt,
00728                                                          'sub_levels' => array() );
00729                 }
00730             }
00731             $this->TransactionIsValid = true;
00732 
00733             if ( $this->isConnected() )
00734             {
00735                 $oldRecordError = $this->RecordError;
00736                 // Turn off error handling while we begin
00737                 $this->RecordError = false;
00738                 $this->beginQuery();
00739                 $this->RecordError = $oldRecordError;
00740 
00741                 // We update the transaction counter after the query, otherwise we
00742                 // mess up the debug background highlighting.
00743                 ++$this->TransactionCounter;
00744             }
00745         }
00746         return true;
00747     }
00748 
00749     /**
00750      * The query to start a transaction.
00751      *
00752      * This function must be reimplemented in the subclasses.
00753      *
00754      * @return bool
00755      */
00756      function beginQuery()
00757     {
00758         return false;
00759     }
00760 
00761     /**
00762      * Commits the current transaction. If this is not the outermost it will not commit
00763      * to the database immediately but instead decrease the transaction counter.
00764      *
00765      * If the current transaction had any errors in it the transaction will be rollbacked
00766      * instead of commited. This ensures that the database is in a valid state.
00767      * Also the PHP execution will be stopped.
00768      *
00769      * @return bool true if the transaction was successful, false otherwise.
00770      */
00771     function commit()
00772     {
00773         $ini = eZINI::instance();
00774         if ($ini->variable( "DatabaseSettings", "Transactions" ) == "enabled")
00775         {
00776             if ( $this->TransactionCounter <= 0 )
00777             {
00778                 eZDebug::writeError( 'No transaction in progress, cannot commit', __METHOD__ );
00779                 return false;
00780             }
00781 
00782             --$this->TransactionCounter;
00783             if ( $this->TransactionCounter == 0 )
00784             {
00785                 if ( is_array( $this->TransactionStackTree ) )
00786                 {
00787                     // Reset the stack debug tree since the top commit was done
00788                     $this->TransactionStackTree = array();
00789                 }
00790                 if ( $this->isConnected() )
00791                 {
00792                     // Check if we have encountered any problems, if so we have to rollback
00793                     if ( !$this->TransactionIsValid )
00794                     {
00795                         $oldRecordError = $this->RecordError;
00796                         // Turn off error handling while we rollback
00797                         $this->RecordError = false;
00798                         $this->rollbackQuery();
00799                         $this->RecordError = $oldRecordError;
00800 
00801                         return false;
00802                     }
00803                     else
00804                     {
00805                         $oldRecordError = $this->RecordError;
00806                         // Turn off error handling while we commit
00807                         $this->RecordError = false;
00808                         $this->commitQuery();
00809                         $this->RecordError = $oldRecordError;
00810                     }
00811                 }
00812             }
00813             else
00814             {
00815                 if ( is_array( $this->TransactionStackTree ) )
00816                 {
00817                     // Close the last open nested transaction
00818                     $bt = debug_backtrace();
00819                     // Store commit trace
00820                     $subLevels =& $this->TransactionStackTree['sub_levels'];
00821                     for ( $i = 1; $i < $this->TransactionCounter; ++$i )
00822                     {
00823                         $subLevels =& $subLevels[count( $subLevels ) - 1]['sub_levels'];
00824                     }
00825                     // Find last entry and add the commit trace
00826                     $subLevels[count( $subLevels ) - 1]['commit_trace'] = $bt;
00827                 }
00828             }
00829         }
00830         return true;
00831     }
00832 
00833     /**
00834      * The query to commit the transaction.
00835      *
00836      * This function must be reimplemented in the subclasses.
00837      *
00838      * @return bool
00839      */
00840     function commitQuery()
00841     {
00842         return false;
00843     }
00844 
00845     /**
00846      * Cancels the transaction.
00847      *
00848      * @return bool
00849      */
00850     function rollback()
00851     {
00852         if ( is_array( $this->TransactionStackTree ) )
00853         {
00854             // All transactions were rollbacked, reset the tree.
00855             $this->TransactionStackTree = array();
00856         }
00857         $ini = eZINI::instance();
00858         if ($ini->variable( "DatabaseSettings", "Transactions" ) == "enabled")
00859         {
00860             if ( $this->TransactionCounter <= 0 )
00861             {
00862                 eZDebug::writeError( 'No transaction in progress, cannot rollback', __METHOD__ );
00863                 return false;
00864             }
00865             // Reset the transaction counter
00866             $this->TransactionCounter = 0;
00867             if ( $this->isConnected() )
00868             {
00869                 $oldRecordError = $this->RecordError;
00870                 // Turn off error handling while we rollback
00871                 $this->RecordError = false;
00872                 $this->rollbackQuery();
00873                 $this->RecordError = $oldRecordError;
00874             }
00875         }
00876         return true;
00877     }
00878 
00879     /*!
00880 
00881     */
00882     /**
00883      * Goes through the transaction stack tree {@see eZDBInterface::$TransactionStackTree},
00884      * generates the text output for it and returns it.
00885      *
00886      * @return bool|string The generated string or false if it is disabled.
00887      */
00888     function generateFailedTransactionStack()
00889     {
00890         if ( !$this->TransactionStackTree )
00891         {
00892             return false;
00893         }
00894         return $this->generateFailedTransactionStackEntry( $this->TransactionStackTree, 0 );
00895     }
00896 
00897     /**
00898      * Recursive helper function for generating stack tree output.
00899      *
00900      * @access private
00901      * @param array $stack
00902      * @param int $indentCount
00903      * @return string The generated string
00904      */
00905     function generateFailedTransactionStackEntry( $stack, $indentCount )
00906     {
00907         $stackText = '';
00908         $indent = '';
00909         if ( $indentCount > 0 )
00910         {
00911             $indent = str_repeat( " ", $indentCount*4 );
00912         }
00913         $stackText .= $indent . "Level " . $stack['level'] . "\n" . $indent . "{" . $indent . "\n";
00914         $stackText .= $indent . "  Began at:\n";
00915         for ( $i = 0; $i < 2 && $i < count( $stack['trace'] ); ++$i )
00916         {
00917             $indent2 = str_repeat( "  ", $i + 1 );
00918             if ( $i > 0 )
00919             {
00920                 $indent2 .= "->";
00921             }
00922             $stackText .= $indent . $indent2 . $this->generateTraceEntry( $stack['trace'][$i] );
00923             $stackText .= "\n";
00924         }
00925         foreach ( $stack['sub_levels'] as $subStack )
00926         {
00927             $stackText .= $this->generateFailedTransactionStackEntry( $subStack, $indentCount + 1 );
00928         }
00929         if ( isset( $stack['commit_trace'] ) )
00930         {
00931             $stackText .= $indent . "  And commited at:\n";
00932             for ( $i = 0; $i < 2 && $i < count( $stack['commit_trace'] ); ++$i )
00933             {
00934                 $indent2 = str_repeat( "  ", $i + 1 );
00935                 if ( $i > 0 )
00936                 {
00937                     $indent2 .= "->";
00938                 }
00939                 $stackText .= $indent . $indent2 . $this->generateTraceEntry( $stack['commit_trace'][$i] );
00940                 $stackText .= "\n";
00941             }
00942         }
00943         $stackText .= $indent . "}" . "\n";
00944         return $stackText;
00945     }
00946 
00947     /**
00948      * Helper function for generating output for one stack-trace entry.
00949      *
00950      * @access private
00951      * @param array $entry
00952      * @return string The generated string
00953      */
00954     function generateTraceEntry( $entry )
00955     {
00956         if ( isset( $entry['file'] ) )
00957         {
00958             $stackText = $entry['file'];
00959         }
00960         else
00961         {
00962             $stackText = "???";
00963         }
00964         $stackText .= ":";
00965         if ( isset( $entry['line'] ) )
00966         {
00967             $stackText .= $entry['line'];
00968         }
00969         else
00970         {
00971             $stackText .= "???";
00972         }
00973         $stackText .= " ";
00974         if ( isset( $entry['class'] ) )
00975         {
00976             $stackText .= $entry['class'];
00977         }
00978         else
00979         {
00980             $stackText .= "???";
00981         }
00982         $stackText .= "::";
00983         if ( isset( $entry['function'] ) )
00984         {
00985             $stackText .= $entry['function'];
00986         }
00987         else
00988         {
00989             $stackText .= "???";
00990         }
00991         return $stackText;
00992     }
00993 
00994     /**
00995      * The query to cancel the transaction.
00996      *
00997      * This function must be reimplemented in the subclasses.
00998      *
00999      * @return bool
01000      */
01001     function rollbackQuery()
01002     {
01003         return false;
01004     }
01005 
01006     /**
01007      * Invalidates the current transaction, see {@see commit()} for more details on this.
01008      *
01009      * @see isTransactionValid()
01010      * @return bool true if it was invalidated or false if there is no transaction to invalidate.
01011      */
01012     function invalidateTransaction()
01013     {
01014         if ( $this->TransactionCounter <= 0 )
01015             return false;
01016         $this->TransactionIsValid = false;
01017         return true;
01018     }
01019 
01020     /**
01021      * This is called whenever an error occurs in one of the database handlers.
01022      *
01023      * If a transaction is active it will be invalidated as well.
01024      *
01025      * @access protected
01026      * @throws eZDBException
01027      */
01028     function reportError()
01029     {
01030         // If we have a running transaction we must mark as invalid
01031         // in which case a call to commit() will perform a rollback
01032         if ( $this->TransactionCounter > 0 )
01033         {
01034             $this->invalidateTransaction();
01035 
01036             // This is the unique ID for this incidence which will also be placed in the error logs.
01037             $transID = 'TRANSID-' . md5( time() . mt_rand() );
01038 
01039             eZDebug::writeError( 'Transaction in progress failed due to DB error, transaction was rollbacked. Transaction ID is ' . $transID . '.', 'eZDBInterface::commit ' . $transID );
01040 
01041             $this->rollback();
01042 
01043             if ( $this->errorHandling == eZDB::ERROR_HANDLING_EXCEPTIONS )
01044             {
01045                 throw new eZDBException( $this->ErrorMessage, $this->ErrorNumber );
01046             }
01047             else
01048             {
01049                 // Stop execution immediately while allowing other systems (session etc.) to cleanup
01050                 eZExecution::cleanup();
01051                 eZExecution::setCleanExit();
01052 
01053                 // Give some feedback, and also possibly show the debug output
01054                 eZDebug::setHandleType( eZDebug::HANDLE_NONE );
01055 
01056                 $ini = eZINI::instance();
01057                 $adminEmail = $ini->variable( 'MailSettings', 'AdminEmail' );
01058                 if ( !eZSys::isShellExecution() )
01059                 {
01060                     if ( !headers_sent() )
01061                     {
01062                         header("HTTP/1.1 500 Internal Server Error");
01063                     }
01064                     $site = eZSys::serverVariable( 'HTTP_HOST' );
01065                     $uri = eZSys::serverVariable( 'REQUEST_URI' );
01066 
01067                     print( "<div class=\"fatal-error\" style=\"" );
01068                     print( 'margin: 0.5em 0 1em 0; ' .
01069                            'padding: 0.25em 1em 0.75em 1em;' .
01070                            'border: 4px solid #000000;' .
01071                            'background-color: #f8f8f4;' .
01072                            'border-color: #f95038;" >' );
01073                     print( "<b>Fatal error</b>: A database transaction in eZ Publish failed.<br/>" );
01074                     print( "<p>" );
01075                     print( "The current execution was stopped to prevent further problems.<br/>\n" .
01076                            "You should contact the <a href=\"mailto:$adminEmail?subject=Transaction failed on $site and URI $uri with ID $transID\">System Administrator</a> of this site with the information on this page.<br/>\n" .
01077                            "The current transaction ID is <b>$transID</b> and has been logged.<br/>\n" .
01078                            "Please include the transaction ID and the current URL when contacting the system administrator.<br/>\n" );
01079                     print( "</p>" );
01080                     print( "</div>" );
01081 
01082                     $templateResult = null;
01083                     if ( function_exists( 'eZDisplayResult' ) )
01084                     {
01085                         eZDisplayResult( $templateResult );
01086                     }
01087                 }
01088                 else
01089                 {
01090                     fputs( STDERR,"Fatal error: A database transaction in eZ Publish failed.\n" );
01091                     fputs( STDERR, "\n" );
01092                     fputs( STDERR, "The current execution was stopped to prevent further problems.\n" .
01093                            "You should contact the System Administrator ($adminEmail) of this site.\n" .
01094                            "The current transaction ID is $transID and has been logged.\n" .
01095                            "Please include the transaction ID and the name of the current script when contacting the system administrator.\n" );
01096                     fputs( STDERR, "\n" );
01097 
01098                     fputs( STDERR, eZDebug::printReport( false, false, true ) );
01099                 }
01100 
01101                 // PHP execution stops here
01102                 exit( 1 );
01103             }
01104         }
01105     }
01106 
01107     /**
01108      * Returns if the current or last running transaction is valid
01109      *
01110      * @see invalidateTransaction()
01111      * @return bool true if the current or last running transaction was valid, false otherwise
01112      */
01113     function isTransactionValid()
01114     {
01115         return $this->TransactionIsValid;
01116     }
01117 
01118     /**
01119      * Returns the current transaction counter.
01120      *
01121      * 0 means no transactions, 1 or higher means 1 or more transactions are running and
01122      * a negative value means something is wrong.
01123      *
01124      * @return int
01125      */
01126     function transactionCounter()
01127     {
01128         return $this->TransactionCounter;
01129     }
01130 
01131     /**
01132      * Returns the relation count for all relation types in the mask $relationMask.
01133      *
01134      * @param int $relationMask
01135      * @return int
01136      */
01137     function relationCounts( $relationMask )
01138     {
01139     }
01140 
01141     /**
01142      * Returns the number of relation objects in the database for the relation type $relationType.
01143      *
01144      * @param int $relationType
01145      * @return int
01146      */
01147     function relationCount( $relationType = eZDBInterface::RELATION_TABLE )
01148     {
01149     }
01150 
01151     /**
01152      * Returns the existing ez publish tables in database
01153      *
01154      * @param int $server
01155      * @return array
01156      */
01157     function eZTableList( $server = self::SERVER_MASTER )
01158     {
01159     }
01160 
01161     /**
01162      * Returns the relation names in the database as an array for the relation type $relationType.
01163      *
01164      * @param int $relationType
01165      * @return array
01166      */
01167     function relationList( $relationType = eZDBInterface::RELATION_TABLE )
01168     {
01169     }
01170 
01171     /**
01172      * Tries to remove the relation type $relationType named $relationName
01173      *
01174      * @param string $relationName
01175      * @param int $relationType
01176      * @return bool true if successful
01177      */
01178     function removeRelation( $relationName, $relationType )
01179     {
01180         return false;
01181     }
01182 
01183     /**
01184      * Returns the name of the relation type which is usable in SQL or false if unknown type.
01185      *
01186      * This function can be used by some database handlers which can operate on relation types using SQL.
01187      *
01188      * @access protected
01189      * @param int $relationType
01190      * @return bool
01191      */
01192     function relationName( $relationType )
01193     {
01194         $names = array( eZDBInterface::RELATION_TABLE => 'TABLE',
01195                         eZDBInterface::RELATION_SEQUENCE => 'SEQUENCE',
01196                         eZDBInterface::RELATION_TRIGGER => 'TRIGGER',
01197                         eZDBInterface::RELATION_VIEW => 'VIEW',
01198                         eZDBInterface::RELATION_INDEX => 'INDEX' );
01199         if ( !isset( $names[$relationType] ) )
01200             return false;
01201         return $names[$relationType];
01202     }
01203 
01204     /**
01205      * Return A regexp (PCRE) that can be used to filter out certain relation elements.
01206      * If no special regexp is provided it will return false.
01207      *
01208      * An example, will only match tables that start with 'ez'.
01209      * <code>
01210      * return "#^ez#";
01211      * </code>
01212      *
01213      * This function is currently used by the eZDBTool class to remove relation elements of a specific kind
01214      * (Most likely eZ Publish related elements).
01215      *
01216      * @param int $relationType The type which needs to be filtered, this allows one regexp per type.
01217      * @return bool
01218      */
01219     function relationMatchRegexp( $relationType )
01220     {
01221         return false;
01222     }
01223 
01224     /**
01225      * Casts elements of $pieces to type $type and returns them as string separated by $glue.
01226      *
01227      * Use {@see generateSQLINStatement()} if you intend to use this for IN statments!
01228      * Example:
01229      * <code>
01230      * $this->implodeWithTypeCast( ',', $myArray, 'int' );
01231      * </code>
01232      *
01233      * @param string $glue The separator.
01234      * @param array $pieces The array containing the elements.
01235      * @param string $type The type to cast to.
01236      * @return string
01237      */
01238     function implodeWithTypeCast( $glue, &$pieces, $type )
01239     {
01240         $str = '';
01241         if ( !is_array( $pieces ) )
01242             return $str;
01243 
01244         foreach( $pieces as $piece )
01245         {
01246             settype( $piece, $type );
01247             $str .= $piece.$glue;
01248         }
01249         $str = rtrim( $str, $glue );
01250         return $str;
01251     }
01252 
01253     /**
01254      * Returns the last serial ID generated with an auto increment field.
01255      *
01256      * @param string|bool $table
01257      * @param string|bool $column
01258      */
01259     function lastSerialID( $table = false, $column = false )
01260     {
01261     }
01262 
01263     /**
01264      * Will escape a string so it's ready to be inserted in the database.
01265      *
01266      * @param string $str
01267      * @return string mixed
01268      */
01269     function escapeString( $str )
01270     {
01271         return $str;
01272     }
01273 
01274     /**
01275      * Will close the database connection.
01276      *
01277      * @return void
01278      */
01279     function close()
01280     {
01281     }
01282 
01283     /**
01284      * Returns true if we're connected to the database backend.
01285      *
01286      * @access protected
01287      * @return bool
01288      */
01289     function isConnected()
01290     {
01291         return $this->IsConnected;
01292     }
01293 
01294     /**
01295      * Create a new database
01296      *
01297      * @param string $dbName
01298      * @return void
01299      */
01300     function createDatabase( $dbName )
01301     {
01302     }
01303 
01304     /**
01305      * Removes a database
01306      *
01307      * @param string $dbName
01308      * @return void
01309      */
01310     function removeDatabase( $dbName )
01311     {
01312     }
01313 
01314     /**
01315      * Create a new temporary table
01316      *
01317      * @param string $createTableQuery
01318      * @param int $server
01319      */
01320     function createTempTable( $createTableQuery = '', $server = self::SERVER_SLAVE )
01321     {
01322         $this->query( $createTableQuery, $server );
01323     }
01324 
01325     /**
01326      * Drop temporary table
01327      *
01328      * @param string $dropTableQuery
01329      * @param int $server
01330      * @return void
01331      */
01332     function dropTempTable( $dropTableQuery = '', $server = self::SERVER_SLAVE )
01333     {
01334         $this->query( $dropTableQuery, $server );
01335     }
01336 
01337     /**
01338      * Drop temporary table list
01339      *
01340      * @param array $tableList
01341      * @param int $server
01342      */
01343     function dropTempTableList( $tableList, $server = self::SERVER_SLAVE )
01344     {
01345         foreach( $tableList as $tableName )
01346             $this->dropTempTable( "DROP TABLE $tableName", $server );
01347     }
01348 
01349     /**
01350      * Sets the error message and error message number
01351      *
01352      * @return void
01353      */
01354     function setError()
01355     {
01356     }
01357 
01358     /**
01359      * Returns the error message
01360      *
01361      * @return string
01362      */
01363     function errorMessage()
01364     {
01365         return $this->ErrorMessage;
01366     }
01367 
01368     /**
01369      * Returns the error number
01370      *
01371      * @return int
01372      */
01373     function errorNumber()
01374     {
01375         return $this->ErrorNumber;
01376     }
01377 
01378     /**
01379      * Returns an array of available databases in the database, null of none available,
01380      * false if listing databases not supported by database
01381      *
01382      * @return array|null|bool
01383      */
01384     function availableDatabases()
01385     {
01386         return false;
01387     }
01388 
01389     /*!
01390 
01391 
01392 
01393     */
01394     /**
01395      * Generate unique table name basing on the given pattern.
01396      *
01397      * If the pattern contains a (%) character then the character
01398      * is replaced with a part providing uniqueness (e.g. random number).
01399      *
01400      * @param string $pattern
01401      * @param bool $randomizeIndex
01402      * @param int $server
01403      * @return string
01404      */
01405     function generateUniqueTempTableName( $pattern, $randomizeIndex = false, $server = self::SERVER_SLAVE )
01406     {
01407         $tableList = array_keys( $this->eZTableList( $server ) );
01408         if ( $randomizeIndex === false )
01409         {
01410             $randomizeIndex = mt_rand( 10, 1000 );
01411         }
01412         do
01413         {
01414             $uniqueTempTableName = str_replace( '%', $randomizeIndex, $pattern );
01415             $randomizeIndex++;
01416         } while ( in_array( $uniqueTempTableName, $tableList ) );
01417 
01418         return $uniqueTempTableName;
01419     }
01420 
01421     /**
01422      * Get database version number
01423      *
01424      * @return string|bool Version number, false if not supported
01425      */
01426     function version()
01427     {
01428         return false;
01429     }
01430 
01431     /**
01432      * This function can be used to create a SQL IN statement to be used in a WHERE clause:
01433      *
01434      * WHERE columnName IN ( element1, element2, ... )
01435      * By default, the elements that can be submitted as an anonymous array (or an integer value
01436      * in case of a single element) will just be imploded. Drivers for databases with a limitation
01437      * of the elements within an IN statement have to reimplement this function. It is also possible
01438      * to negate the "IN" to a "NOT IN" by using the last parameter of this function.
01439      *
01440      * Usage:
01441      *
01442      * $db =& eZDb::instance();
01443      * $db->generateSQLINStatement( array( 2, 5, 43, ) );
01444      *
01445      * @param int|array $elements
01446      *        Elements that should (not) be matched by the IN statment as an
01447      *        integer or anonymous array
01448      * @param string $columnName
01449      *        Column name of the database table the IN statement should be
01450      *        created for
01451      * @param bool $not
01452      *        Will generate a "NOT IN" ( if set to true ) statement instead
01453      *        of an "IN" ( if set to false , default )
01454      * @param $unique
01455      *        Wether or not to make the array unique. Not implemented in this
01456      *        class, but can be used by extending classes (oracle does use it)
01457      * @param $type The type to cast the array elements to
01458      *
01459      * @return string A string with the correct IN statement like for example
01460      *         "columnName IN ( element1, element2 )"
01461      */
01462     function generateSQLINStatement( $elements, $columnName = '', $not = false, $unique = true, $type = false )
01463     {
01464         $result    = '';
01465         $statement = $columnName . ' IN';
01466         if ( $not === true )
01467         {
01468             $statement = $columnName . ' NOT IN';
01469         }
01470 
01471         if ( !is_array( $elements ) )
01472         {
01473             $elements = array( $elements );
01474         }
01475 
01476         $impString = $type ? $this->implodeWithTypeCast( ', ', $elements, $type ) : implode( ', ', $elements );
01477         $result = $statement . ' ( ' . $impString . ' )';
01478 
01479         return $result;
01480     }
01481 
01482     /**
01483      * Returns true if the database handler support the insertion of default values, false if not
01484      *
01485      * @return bool
01486      */
01487     function supportsDefaultValuesInsertion()
01488     {
01489         return true;
01490     }
01491 
01492     /**
01493      * Sets the eZDB error handling mode
01494      * @param int $errorHandling
01495      *        Possible values are:pm
01496      *        - eZDB::ERROR_HANDLING_STANDARD: backward compatible error handling, using reportError
01497      *        - eZDB::ERROR_HANDLING_EXCEPTION: using exceptions
01498      * @since 4.5
01499      */
01500     public function setErrorHandling( $errorHandling )
01501     {
01502         if ( $errorHandling != eZDB::ERROR_HANDLING_EXCEPTIONS &&
01503              $errorHandling != eZDB::ERROR_HANDLING_STANDARD )
01504             throw new RuntimeException( "Unknown eZDB error handling mode $errorHandling" );
01505 
01506         $this->errorHandling = $errorHandling;
01507     }
01508 
01509     /**
01510      * Contains the current server
01511      *
01512      * @access protected
01513      * @var string
01514      */
01515     public $Server;
01516 
01517     /**
01518      * Contains the current port
01519      *
01520      * @access protected
01521      * @var int
01522      */
01523     public $Port;
01524 
01525     /**
01526      * The socket path, used by MySQL
01527      *
01528      * @access protected
01529      * @var string
01530      */
01531     public $SocketPath;
01532 
01533     /**
01534      * The current database name
01535      *
01536      * @access protected
01537      * @var string
01538      */
01539     public $DB;
01540 
01541     /**
01542      * The current connection, false if not connection has been made
01543      *
01544      * @access protected
01545      * @var resource|bool
01546      */
01547     public $DBConnection;
01548 
01549     /**
01550      * Contains the write database connection if used
01551      *
01552      * @access protected
01553      * @var resource|bool
01554      */
01555     public $DBWriteConnection;
01556 
01557     /**
01558      * Stores the database connection user
01559      *
01560      * @access protected
01561      * @var string
01562      */
01563     public $User;
01564 
01565     /**
01566      * Stores the database connection password
01567      *
01568      * @access protected
01569      * @var string
01570      */
01571     public $Password;
01572 
01573     /**
01574      * The charset used for the current database
01575      *
01576      * @access protected
01577      * @var string
01578      */
01579     public $Charset;
01580 
01581     /**
01582      * The number of times to retry a connection if it fails
01583      *
01584      * @access protected
01585      * @var int
01586      */
01587     public $ConnectRetries;
01588 
01589     /**
01590      * Instance of a textcodec which handles text conversion, may not be set if no builtin encoding is used
01591      *
01592      * @access protected
01593      * @var eZTextCodec|null|bool
01594      */
01595     public $OutputTextCodec;
01596 
01597     /**
01598      * Instance of a textcodec which handles text conversion, may not be set if no builtin encoding is used
01599      *
01600      * @access protected
01601      * @var eZTextCodec|null|bool
01602      */
01603     public $InputTextCodec;
01604 
01605     /**
01606      * True if a builtin encoder is to be used, this means that all input/output text is converted
01607      *
01608      * @access protected
01609      * @var bool
01610      */
01611     public $UseBuiltinEncoding;
01612 
01613     /**
01614      * Setting if SQL queries should be sent to debug output
01615      *
01616      * @access protected
01617      * @var bool
01618      */
01619     public $OutputSQL;
01620 
01621     /**
01622      * Contains true if we're connected to the database backend
01623      *
01624      * @access protected
01625      * @var bool
01626      */
01627     public $IsConnected = false;
01628 
01629     /**
01630      * Contains number of queries sended to DB
01631      *
01632      * @access protected
01633      * @var int
01634      */
01635     public $NumQueries = 0;
01636 
01637     /**
01638      * The start time of the timer
01639      *
01640      * @access protected
01641      * @var bool|float
01642      */
01643     public $StartTime;
01644 
01645     /**
01646      * The end time of the timer
01647      *
01648      * @access protected
01649      * @var bool|float
01650      */
01651     public $EndTime;
01652 
01653     /**
01654      * The total number of milliseconds the timer took
01655      *
01656      * @access protected
01657      * @var bool|float
01658      */
01659     public $TimeTaken;
01660 
01661     /**
01662      * The database error message of the last executed function
01663      *
01664      * @access protected
01665      * @var string
01666      */
01667     public $ErrorMessage;
01668 
01669     /**
01670      * The database error message number of the last executed function
01671      *
01672      * @access protected
01673      * @var int
01674      */
01675     public $ErrorNumber = 0;
01676 
01677     /**
01678      * If true then ErrorMessage and ErrorNumber get filled
01679      *
01680      * @access protected
01681      * @var bool
01682      */
01683     public $RecordError = true;
01684 
01685     /**
01686      * If true then the database connection should be persistent
01687      *
01688      * @access protected
01689      * @var bool
01690      */
01691     public $UsePersistentConnection = false;
01692 
01693     /**
01694      * True if slave servers are enabled
01695      *
01696      * @access protected
01697      * @var bool
01698      */
01699     public $UseSlaveServer;
01700 
01701     /**
01702      * The slave database name
01703      *
01704      * @access protected
01705      * @var string
01706      */
01707     public $SlaveDB;
01708 
01709     /**
01710      * The slave server name
01711      *
01712      * @access protected
01713      * @var string
01714      */
01715     public $SlaveServer;
01716 
01717     /**
01718      * The slave server port
01719      *
01720      * @access protected
01721      * @var int
01722      */
01723     public $SlavePort;
01724 
01725     /**
01726      * The slave database user
01727      *
01728      * @access protected
01729      * @var string
01730      */
01731     public $SlaveUser;
01732 
01733     /**
01734      * The slave database user password
01735      *
01736      * @access protected
01737      * @var string
01738      */
01739     public $SlavePassword;
01740 
01741     /**
01742      * The transaction counter, 0 means no transaction
01743      *
01744      * @access protected
01745      * @var int
01746      */
01747     public $TransactionCounter;
01748 
01749     /**
01750      * Flag which tells if a transaction is considered valid or not. A transaction will be made invalid if SQL errors occur
01751      *
01752      * @access protected
01753      * @var bool
01754      */
01755     public $TransactionIsValid;
01756 
01757     /**
01758      * Holds the transactions
01759      *
01760      * @access protected
01761      * @var array|bool
01762      */
01763     public $TransactionStackTree;
01764 
01765     /**
01766      * Error handling mechanism
01767      *
01768      * @var int One of the eZDB::ERROR_HANDLING_* constants
01769      */
01770     protected $errorHandling = eZDB::ERROR_HANDLING_STANDARD;
01771 }
01772 
01773 ?>