databasec.php

来自「php 开发的内容管理系统」· PHP 代码 · 共 1,939 行 · 第 1/4 页

PHP
1,939
字号
<?php
// Modified for mediawiki for XOOPS - by D.J.

if(defined("MEDIAWIKI_DATABASE")):
return;
else:
define("MEDIAWIKI_DATABASE", 1);

/**
 * This file deals with MySQL interface functions
 * and query specifics/optimisations
 * @package MediaWiki
 */

/**
 * Depends on the CacheManager
 */
//require_once( 'CacheManager.php' );

/** See Database::makeList() */
define( 'LIST_COMMA', 0 );
define( 'LIST_AND', 1 );
define( 'LIST_SET', 2 );
define( 'LIST_NAMES', 3);
define( 'LIST_OR', 4);

/** Number of times to re-try an operation in case of deadlock */
define( 'DEADLOCK_TRIES', 4 );
/** Minimum time to wait before retry, in microseconds */
define( 'DEADLOCK_DELAY_MIN', 500000 );
/** Maximum time to wait before retry */
define( 'DEADLOCK_DELAY_MAX', 1500000 );

class DBObject {
	var $mData;

	function DBObject($data) {
		$this->mData = $data;
	}

	function isLOB() {
		return false;
	}

	function data() {
		return $this->mData;
	}
};

/**
 * Database abstraction object
 * @package MediaWiki
 */
class mwDatabase {

#------------------------------------------------------------------------------
# Variables
#------------------------------------------------------------------------------
	/**#@+
	 * @access private
	 */
	var $mLastQuery = '';

	var $mServer, $mUser, $mPassword, $mConn = null, $mDBname;
	var $mOut, $mOpened = false;

	var $mFailFunction;
	var $mTablePrefix;
	var $mFlags;
	var $mTrxLevel = 0;
	var $mErrorCount = 0;
	var $mLBInfo = array();
	/**#@-*/

#------------------------------------------------------------------------------
# Accessors
#------------------------------------------------------------------------------
	# These optionally set a variable and return the previous state

	/**
	 * Fail function, takes a Database as a parameter
	 * Set to false for default, 1 for ignore errors
	 */
	function failFunction( $function = NULL ) {
		return wfSetVar( $this->mFailFunction, $function );
	}

	/**
	 * Output page, used for reporting errors
	 * FALSE means discard output
	 */
	function &setOutputPage( &$out ) {
		$this->mOut =& $out;
	}

	/**
	 * Boolean, controls output of large amounts of debug information
	 */
	function debug( $debug = NULL ) {
		return wfSetBit( $this->mFlags, DBO_DEBUG, $debug );
	}

	/**
	 * Turns buffering of SQL result sets on (true) or off (false).
	 * Default is "on" and it should not be changed without good reasons.
	 */
	function bufferResults( $buffer = NULL ) {
		if ( is_null( $buffer ) ) {
			return !(bool)( $this->mFlags & DBO_NOBUFFER );
		} else {
			return !wfSetBit( $this->mFlags, DBO_NOBUFFER, !$buffer );
		}
	}

	/**
	 * Turns on (false) or off (true) the automatic generation and sending
	 * of a "we're sorry, but there has been a database error" page on
	 * database errors. Default is on (false). When turned off, the
	 * code should use wfLastErrno() and wfLastError() to handle the
	 * situation as appropriate.
	 */
	function ignoreErrors( $ignoreErrors = NULL ) {
		return wfSetBit( $this->mFlags, DBO_IGNORE, $ignoreErrors );
	}

	/**
	 * The current depth of nested transactions
	 * @param integer $level
	 */
	function trxLevel( $level = NULL ) {
		return wfSetVar( $this->mTrxLevel, $level );
	}

	/**
	 * Number of errors logged, only useful when errors are ignored
	 */
	function errorCount( $count = NULL ) {
		return wfSetVar( $this->mErrorCount, $count );
	}

	/**
	 * Properties passed down from the server info array of the load balancer
	 */
	function getLBInfo( $name = NULL ) {
		if ( is_null( $name ) ) {
			return $this->mLBInfo;
		} else {
			if ( array_key_exists( $name, $this->mLBInfo ) ) {
				return $this->mLBInfo[$name];
			} else {
				return NULL;
			}
		}
	}

	function setLBInfo( $name, $value = NULL ) {
		if ( is_null( $value ) ) {
			$this->mLBInfo = $name;
		} else {
			$this->mLBInfo[$name] = $value;
		}
	}

	/**#@+
	 * Get function
	 */
	function lastQuery() { return $this->mLastQuery; }
	function isOpen() { return $this->mOpened; }
	/**#@-*/

	function setFlag( $flag ) {
		$this->mFlags |= $flag;
	}

	function clearFlag( $flag ) {
		$this->mFlags &= ~$flag;
	}

	function getFlag( $flag ) {
		return !!($this->mFlags & $flag);
	}

// Modified for mediawiki for XOOPS - by D.J.
	/* compatible with XOOPS */
	function Database( $server = false, $user = false, $password = false, $dbName = false, 
		$failFunction = false, $flags = 0, $tablePrefix = 'get from global' ) {
		$this->mwDatabase( $server, $user, $password, $dbName, $failFunction, $flags, $tablePrefix);
	}
	
#------------------------------------------------------------------------------
# Other functions
#------------------------------------------------------------------------------

	/**#@+
	 * @param string $server database server host
	 * @param string $user database user name
	 * @param string $password database user password
	 * @param string $dbname database name
	 */

	/**
	 * @param failFunction
	 * @param $flags
	 * @param string $tablePrefix Database table prefixes. By default use the prefix gave in LocalSettings.php
	 */
// Modified for mediawiki for XOOPS - by D.J.
	function mwDatabase( $server = false, $user = false, $password = false, $dbName = false, 
		$failFunction = false, $flags = 0, $tablePrefix = 'get from global' ) {

		global $wgOut, $wgDBprefix, $wgCommandLineMode;
		# Can't get a reference if it hasn't been set yet
		if ( !isset( $wgOut ) ) {
			$wgOut = NULL;
		}
		$this->mOut =& $wgOut;

		$this->mFailFunction = $failFunction;
		$this->mFlags = $flags;

		if ( $this->mFlags & DBO_DEFAULT ) {
			if ( $wgCommandLineMode ) {
				$this->mFlags &= ~DBO_TRX;
			} else {
				$this->mFlags |= DBO_TRX;
			}
		}

		/*
		// Faster read-only access
		if ( wfReadOnly() ) {
			$this->mFlags |= DBO_PERSISTENT;
			$this->mFlags &= ~DBO_TRX;
		}*/

		/** Get the default table prefix*/
		if ( $tablePrefix == 'get from global' ) {
			$this->mTablePrefix = $wgDBprefix;
		} else {
			$this->mTablePrefix = $tablePrefix;
		}

		if ( $server ) {
			$this->open( $server, $user, $password, $dbName );
		}
	}

	/**
	 * @static
	 * @param failFunction
	 * @param $flags
	 */
	function newFromParams( $server, $user, $password, $dbName,
		$failFunction = false, $flags = 0 )
	{
		return new mwDatabase( $server, $user, $password, $dbName, $failFunction, $flags );
	}

	/**
	 * Usually aborts on failure
	 * If the failFunction is set to a non-zero integer, returns success
	 */
	function open( $server, $user, $password, $dbName ) {
		global $wguname;

		# Test for missing mysql.so
		# First try to load it
		if (!@extension_loaded('mysql')) {
			@dl('mysql.so');
		}

		# Otherwise we get a suppressed fatal error, which is very hard to track down
		if ( !function_exists( 'mysql_connect' ) ) {
			wfDie( "MySQL functions missing, have you compiled PHP with the --with-mysql option?\n" );
		}

		$this->close();
		$this->mServer = $server;
		$this->mUser = $user;
		$this->mPassword = $password;
		$this->mDBname = $dbName;

		$success = false;

		# Force connecting to XOOPS DB
		if($GLOBALS["xoopsDB"]->conn){
			$this->mConn =& $GLOBALS["xoopsDB"]->conn;
		}else
		
		if ( $this->mFlags & DBO_PERSISTENT ) {
			@/**/$this->mConn = mysql_pconnect( $server, $user, $password );
		} else {
			# Create a new connection...
			if( version_compare( PHP_VERSION, '4.2.0', 'ge' ) ) {
				@/**/$this->mConn = mysql_connect( $server, $user, $password, true );
			} else {
				# On PHP 4.1 the new_link parameter is not available. We cannot
				# guarantee that we'll actually get a new connection, and this
				# may cause some operations to fail possibly.
				@/**/$this->mConn = mysql_connect( $server, $user, $password );
			}
		}

		if ( $dbName != '' ) {
			if ( $this->mConn !== false ) {
				$success = @/**/mysql_select_db( $dbName, $this->mConn );
				if ( !$success ) {
					$error = "Error selecting database $dbName on server {$this->mServer} " .
						"from client host {$wguname['nodename']}\n";
					wfDebug( $error );
				}
			} else {
				wfDebug( "DB connection error\n" );
				wfDebug( "Server: $server, User: $user, Password: " .
					substr( $password, 0, 3 ) . "..., error: " . mysql_error() . "\n" );
				$success = false;
			}
		} else {
			# Delay USE query
			$success = (bool)$this->mConn;
		}

		if ( !$success ) {
			$this->reportConnectionError();
		}

		global $wgDBmysql5;
		if( $wgDBmysql5 ) {
			// Tell the server we're communicating with it in UTF-8.
			// This may engage various charset conversions.
			$this->query( 'SET NAMES utf8' );
		}

		$this->mOpened = $success;
		return $success;
	}
	/**#@-*/

	/**
	 * Closes a database connection.
	 * if it is open : commits any open transactions
	 *
	 * @return bool operation success. true if already closed.
	 */
	function close()
	{
		$this->mOpened = false;
		if ( $this->mConn ) {
			if ( $this->trxLevel() ) {
				$this->immediateCommit();
			}
			return mysql_close( $this->mConn );
		} else {
			return true;
		}
	}

	/**
	 * @access private
	 * @param string $error fallback error message, used if none is given by MySQL
	 */
	function reportConnectionError( $error = 'Unknown error' ) {
		$myError = $this->lastError();
		if ( $myError ) {
			$error = $myError;
		}

		if ( $this->mFailFunction ) {
			if ( !is_int( $this->mFailFunction ) ) {
				$ff = $this->mFailFunction;
				$ff( $this, $error );
			}
		} else {
			wfEmergencyAbort( $this, $error );
		}
	}

	/**
	 * Usually aborts on failure
	 * If errors are explicitly ignored, returns success
	 */
	function query( $sql, $fname = '', $tempIgnore = false ) {
		global $wgProfiling;

		if ( $wgProfiling ) {
			# generalizeSQL will probably cut down the query to reasonable
			# logging size most of the time. The substr is really just a sanity check.

			# Who's been wasting my precious column space? -- TS
			#$profName = 'query: ' . $fname . ' ' . substr( Database::generalizeSQL( $sql ), 0, 255 );

			if ( is_null( $this->getLBInfo( 'master' ) ) ) {
				$queryProf = 'query: ' . substr( Database::generalizeSQL( $sql ), 0, 255 );
				$totalProf = 'Database::query';
			} else {
				$queryProf = 'query-m: ' . substr( Database::generalizeSQL( $sql ), 0, 255 );
				$totalProf = 'Database::query-master';
			}
			wfProfileIn( $totalProf );
			wfProfileIn( $queryProf );
		}

		$this->mLastQuery = $sql;

		# Add a comment for easy SHOW PROCESSLIST interpretation
		if ( $fname ) {
			$commentedSql = preg_replace("/\s/", " /* $fname */ ", $sql, 1);
		} else {
			$commentedSql = $sql;
		}

		# If DBO_TRX is set, start a transaction
		if ( ( $this->mFlags & DBO_TRX ) && !$this->trxLevel() && $sql != 'BEGIN' ) {
			$this->begin();
		}

		if ( $this->debug() ) {
			$sqlx = substr( $commentedSql, 0, 500 );
			$sqlx = strtr( $sqlx, "\t\n", '  ' );
			wfDebug( "SQL: $sqlx\n" );
		}

		# Do the query and handle errors
		$ret = $this->doQuery( $commentedSql );

		# Try reconnecting if the connection was lost
		if ( false === $ret && ( $this->lastErrno() == 2013 || $this->lastErrno() == 2006 ) ) {
			# Transaction is gone, like it or not
			$this->mTrxLevel = 0;
			wfDebug( "Connection lost, reconnecting...\n" );
			if ( $this->ping() ) {
				wfDebug( "Reconnected\n" );
				$ret = $this->doQuery( $commentedSql );
			} else {
				wfDebug( "Failed\n" );
			}
		}

		if ( false === $ret ) {
			$this->reportQueryError( $this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore );
		}

		if ( $wgProfiling ) {
			wfProfileOut( $queryProf );
			wfProfileOut( $totalProf );
		}
		return $ret;
	}

	/**
	 * The DBMS-dependent part of query()
	 * @param string $sql SQL query.
	 */
	function doQuery( $sql ) {
		if( $this->bufferResults() ) {
			$ret = mysql_query( $sql, $this->mConn );
		} else {
			$ret = mysql_unbuffered_query( $sql, $this->mConn );
		}
		return $ret;
	}

	/**
	 * @param $error
	 * @param $errno
	 * @param $sql
	 * @param string $fname
	 * @param bool $tempIgnore
	 */
	function reportQueryError( $error, $errno, $sql, $fname, $tempIgnore = false ) {
		global $wgCommandLineMode, $wgFullyInitialised, $wgColorErrors;
		# Ignore errors during error handling to avoid infinite recursion
		$ignore = $this->ignoreErrors( true );
		++$this->mErrorCount;

		if( $ignore || $tempIgnore ) {
			wfDebug("SQL ERROR (ignored): $error\n");
		} else {
			$sql1line = str_replace( "\n", "\\n", $sql );
			wfLogDBError("$fname\t{$this->mServer}\t$errno\t$error\t$sql1line\n");
			wfDebug("SQL ERROR: " . $error . "\n");
			if ( $wgCommandLineMode || !$this->mOut || empty( $wgFullyInitialised ) ) {
				$message = "A database error has occurred\n" .
				  "Query: $sql\n" .
				  "Function: $fname\n" .
				  "Error: $errno $error\n";

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?