<?php
if(!defined('IN_MICECMS')){header("HTTP/1.0 404 Not Found");die();}
//  数据库抽象层

class DBBase {
	public $adodb;
	public $lastsql;		//最后一次执行的SQL
	private $prefix;
	private $connected;

	// 将 $sqlstring 字符串中的 #__ 替换成表的前缀
	function PrefixReplace($sqlstring) {
		 $sqlstring = str_replace("#__", $this->prefix, $sqlstring);
		 return $sqlstring;
	}

	// 将 $sqlstring 字符串中的表的前缀替换成#__
	function RePrefixReplace($sqlstring) {
		 $sqlstring = str_replace($this->prefix, "#__", $sqlstring);
		 return $sqlstring;
	}

	// 返回数据库名称,在类的内部使用  仅SQLite类型数据库使用
	function _db_name($db_name) {
		$db_type = $this->adodb->dbtype;
		if (strpos($db_type,'sqlite')===0) {
			return MICE_DIR.MICE_PRIVATE.$db_name.'/'.MICE_UID.'_'.$db_name.'.db';
		} else if ($db_type == 'gladius') {
			return MICE_DIR.MICE_PRIVATE.$db_name.'/';
		}
		return $db_name;
	}

	function _db_name_subs($db_name, $subsite, $uid) {
		$db_type = $this->adodb->dbtype;
		if (strpos($db_type,'sqlite')===0) {
			return MICE_DIR.$subsite.'/'.MICE_PRIVATE.$db_name.'/'.MICE_UID.'_'.$db_name.'.db';
		} else if ($db_type == 'gladius') {
			return MICE_DIR.$subsite.'/'.MICE_PRIVATE.$db_name.'/';
		}
		return $db_name;
	}
	
	//建立数据库连接
	function DBBase($db_type=MICE_DB) {
		$this->adodb =& ADONewConnection($db_type, 'pear:meta');
		//$this->adodb =& ADONewConnection($db_type);
		$this->Initialize(MICE_DBHOST,MICE_DBUSERNAME,MICE_DBPASSWORD,MICE_DBNAME,MICE_PREFIX,MICE_SETUP);
		$this->adodb->fetchMode = ADODB_FETCH_ASSOC;
		//$this->adodb->debug_console = true;
	}

	//  $db_prefix 数据表前缀
	//  初始化
	function Initialize($db_host, $db_user, $db_password, $db_name, $db_prefix, $setup = false) {
		
		$this->prefix = $db_prefix;
		$this->connected = @$this->adodb->Connect($db_host,$db_user,$db_password, $this->_db_name($db_name));
		//建立长连接
		//$this->connected = @$this->adodb->PConnect($db_host,$db_user,$db_password, $this->_db_name($db_name));
		if (!$setup && !$this->connected) {
			echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title></title></head><body>'."<Script language='JavaScript'>alert('无法连接数据库,请检查数据库设置!');history.back(-1)</Script></body></html>";
			die();
		}
	}

	function SubInitialize($subsite, $uid, $db_host, $db_user, $db_password, $db_name, $db_prefix) {
		$this->prefix = $db_prefix;
		$this->connected = $this->adodb->Connect($db_host,$db_user,$db_password, $this->_db_name_subs($db_name, $subsite, $uid));
		//$this->connected = $this->adodb->PConnect($db_host,$db_user,$db_password, $this->_db_name_subs($db_name, $subsite, $uid));	//建立长连接
	}
	
	//获取表的字段属性(字段名，字段类型，字段长度等)
	function MetaColumns($table) {
		return $this->adodb->MetaColumns($this->prefix.$table);		//传过来的表名没有前缀，自动加上前缀
	}
	
	//回传目前数据库中全部资料表名称于一个数组中
	function MetaTables() {
		$tables = $this->adodb->MetaTables();
		$r = array();
		$l = strlen($this->prefix);
		foreach($tables as $table) {
			$table = strtolower($table);
			if ( substr($table, 0, $l) === strtolower($this->prefix) )
				$r[] = substr($table,$l);		//去掉了表名的前缀
		}
		return	$r;
	}

	//回传被SQL指令更新或被删除掉的数据笔数。如果数据库不支持，回传一个 false 值
	function Affected_Rows() {
		return $this->adodb->Affected_Rows();
	}
	
	//将一个字符串放在引号内，以送到数据库中,回传一个被引号处理过的字符串
	function Quote($s, $magic = false) {
		$qs = $this->adodb->qstr($s, $magic);
		return substr($qs, 1, strlen($qs)-2);
	}
	
	//回传最后插入时的自动增进值 ID。如果系统不支持，回传 false
	function Insert_ID() {
    	return $this->adodb->Insert_ID();
	}
	
	//执行select指令
	function Select($arg_tables, $what, $extra = '') {
		$arg_tables = $this->PrefixReplace($arg_tables);
		$this->lastsql = 'SELECT '.$what.' FROM '.$arg_tables.$extra;
		return $this->adodb->Execute($this->lastsql);
	}
	
	//执行select指令，将第一条记录结果放在一个数组中返回
	function SelectRow($arg_tables, $what, $extra = '') {
		$arg_tables = $this->PrefixReplace($arg_tables);
		$this->lastsql = 'SELECT '.$what.' FROM '.$arg_tables.$extra;
		$row = $this->adodb->Execute($this->lastsql);
		$row = $row->GetArray(1);
		if (isset($row[0]))
			return $row[0];
		return $row;
	}
	
	//从目前指针位置产生一个数组，索引值从 0 到 $number_of_rows - 1
	function SelectArray($arg_tables, $what, $extra = '') {
		$arg_tables = $this->PrefixReplace($arg_tables);
		$this->lastsql = 'SELECT '.$what.' FROM '.$arg_tables.$extra;
		return $this->adodb->GetArray($this->lastsql);
	}
	
	//SELECT * FROM TABLE LIMIT 3 OFFSET 2 将会回传记录 3,4及5三笔(也就是在记录2之后，回传三笔记录)
	//在ADODB里是以 $connection->SelectLimit('SELECT * FROM TABLE',3,2) 来做的
	function SelectArrayLimit($arg_tables, $what, $extra, $nrows, $offset = -1) {
		$arg_tables = $this->PrefixReplace($arg_tables);
		$db_type = $this->adodb->dbtype;
		/*if (strpos($db_type,'mysql')===0){
			$this->lastsql = 'SELECT '.$what.' FROM '.$arg_tables.$extra;
			$rs = $this->adodb->SelectLimit($this->lastsql, $offset, $nrows);
		}else{
			$this->lastsql = 'SELECT '.$what.' FROM '.$arg_tables.$extra;
			$rs = $this->adodb->SelectLimit($this->lastsql, $nrows, $offset);
		}*/
		$this->lastsql = 'SELECT '.$what.' FROM '.$arg_tables.$extra;
		$rs = $this->adodb->SelectLimit($this->lastsql, $offset, $nrows);
		return $rs->GetArray();
	}
	
	//执行一个sql语句，将一个字段的值放入数组中返回
	function SelectColumn($arg_tables, $what, $extra = '') {
		$rsa = $this->SelectArray($arg_tables, $what, $extra);
		$column = array();
		foreach($rsa as $row) {
			$column[] = current($row); //current,返回数组中当前元素的值
		}
		return $column;
	}

	//执行update指令	
	function Update($arg_tables, $sets, $extra = '') {
		$arg_tables = $this->PrefixReplace($arg_tables);
		$this->lastsql = 'UPDATE '.$arg_tables.' SET '.$sets.$extra;
		return $this->adodb->Execute($this->lastsql);
	}
	
	//执行delete指令
	function Delete($arg_tables, $extra = '') {
		$arg_tables = $this->PrefixReplace($arg_tables);
		$this->lastsql = 'DELETE FROM '.$arg_tables.$extra;
		return $this->adodb->Execute($this->lastsql);
	}
	
	//执行insert指令
	function Insert($arg_tables, $fields, $values) {
		$arg_tables = $this->PrefixReplace($arg_tables);
		$this->lastsql = 'INSERT INTO '.$arg_tables.' ('.$fields.')VALUES('.$values.')';
		return $this->adodb->Execute($this->lastsql);
	}
	
	//创建一个表
	function CreateTable($arg_tables, $schema) {
		$arg_tables = $this->PrefixReplace($arg_tables);
		$this->lastsql = 'CREATE TABLE '.$arg_tables.' ('.$schema.')';
		return $this->adodb->Execute($this->lastsql);
	}
	
	//回传最后状态或是错误讯息。即使没有错误发生，本函数也会回传一个字符串
	function ErrorMsg() {
		return $this->adodb->ErrorMsg();
	}
	
	//当指针被移动到最后一笔时，这个值会被设定成 true 。
	function EOF() {
		return $this->adodb->EOF();
	}
	
	//统计满足条件的记录数
	function SelectCount($arg_tables, $field = '*', $extra = '') {
		$arg_tables = $this->PrefixReplace($arg_tables);
		$extras = split("ORDER",$extra);
		$this->lastsql = 'SELECT COUNT('.$field.') FROM '.$arg_tables.$extras[0];
		$rsa = $this->adodb->GetArray($this->lastsql);
		return $this->_count($rsa);
	}
	
	function _count(&$rsa) {
		if (!isset($rsa[0])) return 0;
		reset($rsa[0]);
		return (int)@current($rsa[0]);
	}
	
	//执行一个sql语句,统计记录数，不推荐
	function Count($sql) {
		$rsa = $this->GetArray($sql);
		return $this->_count($rsa);
	}

	//执行一个sql，将字段的值放入一个数组中并返回，只返回一行记录
	// 推荐使用 ::SelectRow()
	function GetRow($sql) {
		$sql = $this->PrefixReplace($sql);
		$rs = $this->adodb->SelectLimit($sql, 1);
		$arr = $rs->GetArray(1);
		if (isset($arr[0]))
			return $arr[0];
		else
			return $arr;
	}
	
	//执行一个sql，将其中的一个字段的值放入一个数组中并返回
	// 推荐使用 ::SelectColumn()
	function GetColumn($sql) {
		$rsa = $this->GetArray($sql);
		$column = array();
		foreach($rsa as $row) {
			$column[] = current($row);
		}
		return $column;
	}

	//执行一个sql，从目前指针位置产生一个数组，索引值从 0 到 $number_of_rows - 1
	//如果没有被定义返回的记录数，那会到档尾(EOF)
	//推荐使用 ::SelectArray()
	function GetArray($sql, $nrows = -1) {
		$this->lastsql = $this->PrefixReplace($sql);
		return $this->adodb->GetArray($this->lastsql, $nrows);
	}
	
	//执行未处理过的sql语句，本函数自动替换表的前缀
	// 推荐使用 ::Update, ::Select, ::Insert, ::Delete and ::CreateTable
	function Execute($sql) {
		$this->lastsql = $this->PrefixReplace($sql);
		return $this->adodb->Execute($this->lastsql);
	}
	
	//执行未处理过的sql语句，本函数自动替换表的前缀,如果多个表，所有表的前缀都会被替换
	function RawExecute($sql) {
		$this->lastsql = str_replace('#__', $this->prefix, $sql);
		return $this->adodb->Execute($this->lastsql);
	}
	
	//执行未处理过的sql语句，本函数自动替换表的前缀,只替换第一个满足条件的字符串
	function PrefixExecute($sql, $prefix) {
		$this->lastsql = StrReplaceOnce($prefix, $this->prefix, $sql);
		return $this->adodb->Execute($this->lastsql);
	}

	//执行成功会回传一个资料集。完成一个SELECT指令
	//$nrows,返回的记录数,$offset,从第几条记录开始
	function SelectLimit($sql, $nrows, $offset = -1) {
		$this->lastsql = $this->PrefixReplace($sql);
		if (strpos($db_type,'mysql')===0)
			return $this->adodb->SelectLimit($this->lastsql, $offset, $nrows);
		else
			return $this->adodb->SelectLimit($this->lastsql, $nrows, $offset);		
	}

	//显示执行的查询和使用的时间，用户调试模式
	function QueryInfo() {
		return array($this->adodb->query_list,$this->adodb->query_list_time);
	}

	//关闭连接
	function Close() {
		return $this->adodb->Close();
	}
}

?>