Location: PHPKode > scripts > NBBS Wizard > nbbs-wizard/dbdriver.php
<?
/*
The Next BBS - Forums Software
Copyright (C) 2004 Chris F. Ravenscroft

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Questions? We can be reached at http://forums.sf.net
*/

require_once "tidbit.php";

function factoryGetDriver($dblayer="peardb")
{
	if($dblayer=="peardb")
	{
		$dbdriver = new peardbdriver();
	}
	else if($dblayer=="adodb")
	{
		$dbdriver = new adodbdriver();
	}
	else
	{
		die("Error! Wrong db abstraction layer specified: ".$dblayer);
	}
	return $dbdriver;
}

class basicdbdriver
{
var $db;
var $total_queries;
var $total_time;
var $start;
var $queries;
var $report_next_error;

	/**
	 * @return mixed: current database handler
	 */
	function db()
	{
		return $this->db;
	}

	/**
	 * An alias for db()
	 */
	function current()
	{
		return $this->db();
	}

	function prequery($qry, $db=null)
	{
		global $DB, $CONFIG, $COMMON;

		if($CONFIG->debuglevel>=2)
		{
			$this->total_queries++;
			$this->start = $COMMON->microtime_float();
		}
		if($CONFIG->debuglevel>=5)
			$this->queries[] = $qry;
	}

	function postquery($qry, $db=null)
	{
		global $DB, $CONFIG, $COMMON;

		if($CONFIG->debuglevel>=2)
			$this->total_time += ($COMMON->microtime_float()-$this->start);
	}

	/**
	 * Create and execute an 'update' query
	 * @param table String name of a table to query
	 * @param keys_and_alues An associative array of keys and values
	 * @param condition String a 'where' condition
	 * @param db database to query
	 * @return mixed: a result set
	 */
	function update($table, $keys_and_values, $condition=null, $db=null)
	{
		$qry = "UPDATE `".$table."` SET ";
		$bMore = true;
		foreach($keys_and_values as $key=>$value)
		{
			if($bMore)
				$qry .= ", ";
			else
				$bMore = true;

			$qry .= "`".$key."`='".$value."'";
		}
		if($condition!=null)
		{
			$qry .= " WHERE ".$condition;
		}

		return $this->query($qry, $db);
	}

	/**
	 * Create and execute an 'insert' query
	 * @param table String name of a table to query
	 * @param keys_and_alues An associative array of keys and values
	 * @param db database to query
	 * @return mixed: a result set
	 */
	function insert($table, $keys_and_values, $db=null)
	{
		$qry  = "INSERT INTO `".$table."` (";
		$qry2 = ") VALUES (";
		$bMore = true;
		foreach($keys_and_values as $key=>$value)
		{
			if($bMore)
			{
				$qry  .= ", ";
				$qry2 .= ", ";
			}
			else
				$bMore = true;

			$qry  .= "`".$key."`";
			$qry2 .= "'".$value."'";
		}
		$qry .= $qry2 . ")";

		return $this->query($qry, $db);
	}

	function report_next_error()
	{
		$this->report_next_error = true;
	}

	/**
	 * Renders a string harmless, thus avoiding SQL Injection
	 * @param str string to neuter
	 * @param forceescape if true, escape string even if magic quotes are enabled
	 * @return string: neutered string
	 */
	function neuter($str,$forceescape=false)
	{
		if(!$forceescape && get_magic_quotes_gpc())
			return $str;
		else
			return addslashes($str);
#		return DB_common::escapesimple($str);
	}

	/**
	 * Revert a string to its old pre-neutering state
	 * @param str string to de-neuter
	 * @return de-neutered string
	 */
	function undoneuter($str)
	{
		return stripslashes($str);
	}

	/**
	 * @return integer: total query time since this object was instantiated
	 */
	function getTotalTime()
	{
		return $this->total_time;
	}

	/**
	 * For profiling purpose
	 * @return string: various information regarding this session's queries
	 */
	function getDebug()
	{
		global $CONFIG;

		$debug = "";
		if($CONFIG->debuglevel>=2)
			$debug .= "<br />Total DB [{$CONFIG->dblayer}:{$CONFIG->dbengine}] queries: {$this->total_queries}";
		if($CONFIG->debuglevel>=5)
		{
			$debug .="<br />Queries List:";
			for($i=0;$i<count($this->queries);$i++)
				$debug .= "<br />[ ".$this->queries[$i]." ]";
		}
		return $debug;
	}

	/**
	 * For debugging purpose
	 * @param row a result set
	 * @return string: keys and associated values
	 */
	function dumpResult($row)
	{
		$s="";
		foreach($row as $key=>$value)
			$s.=$key." => ".$value."<br />";
		return $s;
	}
}

class peardbdriver extends basicdbdriver
{
	function peardbdriver()
	{
		require_once "DB.php";

		$this->total_queries = 0;
		$this->total_time = 0;
		$this->queries = array();
		$this->report_next_error = false;
		set_magic_quotes_runtime(0);
	}

	/**
	 * Connect to a SQL Database.
	 * @param dbengine Database engine; for instance: 'mysql'
	 * @param dbhost Host where the database is located
	 * @param dbname Database name
	 * @param dbuser Username to use when connecting...
	 * @param dbpass User password
	 */
	function connect($dbengine, $dbhost, $dbname, $dbuser, $dbpass)
	{
		global $COMMON;

		$this->db = DB::connect( "$dbengine://$dbuser:$dbpass@$dbhost/$dbname" );
		if(DB::isError($this->db))
		{
			if($this->report_next_error == true)
			{
				$this->report_next_error = false;
				return null;
			}
			$err = &$this->db;
			die("Unable to open database: ".DB::errorMessage($err->code));
		}
		$this->report_next_error = false;
		return $this->db;
	}

	/**
	 * Cleanup current connection
	 */
	function cleanup()
	{
		$this->db->disconnect();
	}

	/**
	 * Run an SQL Query
	 * @param qry the query
	 * @param db database to query
	 * @return mixed: a result set
	 */
	function query($qry, $db=null)
	{
		global $DB, $CONFIG, $COMMON;

		$this->prequery($qry, $db);

		if($db==null)
			$db = &$this->db;	// Use current
		$res = $db->query($qry);

		$this->postquery($qry, $db);

		if(DB::isError($res))
		{
			if($this->report_next_error == true)
			{
				$this->report_next_error = false;
				return null;
			}

			// Database error handling
			die("SQL Layer Error: ".$res->getMessage()." (".$res->getCode().")<br />Debug Info:<br />".$res->getDebugInfo()."<br />Query [".$qry."]");
		}
		$this->report_next_error = false;
		return $res;
	}

	/**
	 * Similar to mySQL's lastInsertId()
	 * Careful! This method's implementation must use a switch() statement to adapt to each db's specifics
	 * ALSO:
	 * Beware of dbs that will actualy return the ID of the _next_ insert; this is bad for various reasons such as:
	 * - they do not return the ID of the latest insert (duh!)
	 * - when returning a future ID, it seems difficult to maintain the DB's integrity as opposed to getting the latest ID,
	 * which can be understood as 'the latest ID for this connection' as opposed to 'all concurrent connections'
	 * @param tableName name of the table where we had an insert whose id we want to get
	 * @return integer: last insert's id
	*/
	function getLastInsertId($tableName, $db=null)
	{
		if($db==null)
			$db = &$this->db;	// Use current
		$qry = "SELECT LAST_INSERT_ID() FROM {$tableName}";
		$res = $this->query($qry, $db);
		$row = $res->fetchRow(DB_FETCHMODE_ORDERED);
		return $row[0];
	}

	/**
	 * @return integer: Number of rows affected by last INSERT or DELETE statement
	 */
	function affectedRows($db=null)
	{
		if($db==null)
			$db = &$this->db;	// Use current
		return $db->affectedRows();
	}
}

class adodbdriver extends basicdbdriver
{
	function adodbdriver()
	{
		require_once "adodb/adodb.inc.php";

		$this->total_queries = 0;
		$this->total_time = 0;
		$this->queries = array();
		$this->report_next_error = false;
		set_magic_quotes_runtime(0);
	}

	/**
	 * Connect to a SQL Database.
	 * @param dbengine Database engine; for instance: 'mysql'
	 * @param dbhost Host where the database is located
	 * @param dbname Database name
	 * @param dbuser Username to use when connecting...
	 * @param dbpass User password
	 */
	function connect($dbengine, $dbhost, $dbname, $dbuser, $dbpass)
	{
		global $CONFIG, $COMMON;

		$this->db = &ADONewConnection($dbengine);
		if(!$this->db->Connect($dbhost,$dbuser,$dbpass,$dbname))
		{
			if($this->report_next_error == true)
			{
				$this->report_next_error = false;
				return null;
			}
			$err = &$this->db;
			die("Unable to open database.");
		}
		$this->report_next_error = false;
		return $this->db;
	}

	/**
	 * Cleanup current connection
	 */
	function cleanup()
	{
		$this->db->Close();
	}

	/**
	 * Run an SQL Query
	 * @param qry the query
	 * @param db database to query
	 * @return mixed: a result set
	 */
	function query($qry, $db=null)
	{
		global $DB, $CONFIG, $COMMON;

		$this->prequery($qry, $db);

		if($db==null)
			$db = &$this->db;	// Use current
		$res = $db->query($qry);

		$this->postquery($qry, $db);

		if(!$res)
		{
			if($this->report_next_error == true)
			{
				$this->report_next_error = false;
				return null;
			}

			// Database error handling
			die("SQL Layer Error: ".$db->ErrorMsg()."<br />Query [".$qry."]");
		}
		$this->report_next_error = false;
		return $res;
	}

	/**
	 * Similar to mySQL's lastInsertId()
	 * Careful! This method's implementation must use a switch() statement to adapt to each db's specifics
	 * ALSO:
	 * Beware of dbs that will actualy return the ID of the _next_ insert; this is bad for various reasons such as:
	 * - they do not return the ID of the latest insert (duh!)
	 * - when returning a future ID, it seems difficult to maintain the DB's integrity as opposed to getting the latest ID,
	 * which can be understood as 'the latest ID for this connection' as opposed to 'all concurrent connections'
	 * @param tableName name of the table where we had an insert whose id we want to get
	 * @return integer: last insert's id
	*/
	function getLastInsertId($tableName, $db=null)
	{
		if($db==null)
			$db = &$this->db;	// Use current
		$qry = "SELECT LAST_INSERT_ID() FROM {$tableName}";
		$res = $this->query($qry, $db);
		$row = $res->fetchRow(DB_FETCHMODE_ORDERED);
		return $row[0];
	}

	/**
	 * @return integer: Number of rows affected by last INSERT or DELETE statement
	 */
	function affectedRows($db=null)
	{
		if($db==null)
			$db = &$this->db;	// Use current
		return $db->Affected_Rows();
	}
}
?>
Return current item: NBBS Wizard