|
eZ Publish
[trunk]
|
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 ?>