<?php
/*
	缩略版ADODB(数据库操作类) by zain
	文件名：class_adodb.php
	创建日期：2011.3.7
	更改日期：2011.3.7
*/
class TINY_ADODB {
	var $type = "mysql";
	var $host;
	var $user;
	var $pass;
	var $database;
	var $char = "utf8";
	var $pconnect;
	var $linkId = 0;
	var $arr;
	var $debug;
	var $dieMethod = 2;###1:return false and continue; # 2:die Msg###
	var $costtime = array();
	var $fetchMode = MYSQL_BOTH;
	var $debuglog;

	// add by tyb 2011-3-10
	var $server_reads=array();
	var $link_read_ids=array();
        var $link_read_id = 0;
	var $forceprivateflag=false;

	// 增加参数 $server_reads: 读库; $forceprivateflag: 是否强制读取主库
	function TINY_ADODB($type, $host = NULL, $user = NULL,$pass = NULL, $database = NULL,$char = NULL, $debug = NULL, $pconnect = NULL, $server_reads=array(), $forceprivateflag=false) {
		if(!is_null($type)) $this->type=$type;
		if(!is_null($host)) $this->host=$host;
		if(!is_null($user)) $this->user=$user;
		if(!is_null($pass)) $this->pass=$pass;
		if(!is_null($database)) $this->database=$database;
		if(!is_null($char)) $this->char=$char;
		if(!is_null($debug))$this->debug = $debug;
		if(!is_null($pconnect))$this->pconnect = $pconnect;

		if(!is_null($server_reads))$this->server_reads = $server_reads;
		if(!is_null($forceprivateflag))$this->forceprivateflag = $forceprivateflag;

		$this->linkId = $this->Connection();
	}

	function CheckLink($sql){
		if ($sql == '') return false;
		if (!$this -> linkId) return false;
		if ($this -> debug)
			$this->costtime && $this->costtime[0] = $this->GetMicTime();
	}

	function Insert_ID(){
		$insertId = mysql_insert_id($this->linkId);
		return $insertId;
	}

	function Affected_Rows() {
		return mysql_affected_rows($this->linkId);
	}

	function Execute($sql,$unbuffered=0,$forceprivate=false){
		$this->CheckLink($sql);

		if($unbuffered && $this->CheckVersion()>4060 && @function_exists('mysql_unbuffered_query')){
			$func = "mysql_unbuffered_query";
		}else{
			$func = "mysql_query";
		}

		$readfromprivate=true;
		if($forceprivate==false) $forceprivate=$this->forceprivateflag;

		if($this->link_read_id){
			if($forceprivate==false&&(substr(trim(strtoupper($sql)),0,6)=="SELECT")){
				$result=$func($sql,$this->link_read_id);
			}

			if($result) $readfromprivate=false;
		}

		if($readfromprivate==true){
			$result = @mysql_query($sql,$this -> linkId);
		}

		if($this->debug){
			$this->costtime[1] = $this->GetMicTime();
			$costtime = substr(($this->costtime[1]-$this->costtime[0])*1000,0,10);
			$this->debuglog .= "[Debug]\n执行：$sql\n花费：$costtime 毫秒\n时间：".date("Y-m-d H:i:s")."\n\n";
		}

		if($unbuffered){
			$ret = $result;
		}else{
			if($result==false) return false;
			$ret = new TINY_ADODB_ARRAY(&$result,$this->fetchMode,$this->dieMethod);
		}

		return $ret;
	}

	function SelectLimit($sql,$offset_b,$offset_n=0,$forceprivate=false){
		$this->CheckLink($sql);
		if(!$offset_n){
			$limit = " limit ".$offset_b;
		}else{
			$limit = " limit ".$offset_b.",".$offset_n;
		}
		$sql.=$limit;
		$result = $this->Execute($sql,$forceprivate);
		return $result;
	}

	function GetOne($sql,$forceprivate=false){
		$ret = $this->SelectLimit($sql,1,0,$forceprivate);
		if(!$ret)
			$this->Halt("执行SQL：".$sql."无法返回一个有效的数据集");
		$result = $ret->GetOne();
		return $result;
	}

	/*
	function GetRow($sql){
		$row = &$this->GetOne($sql);
		return $row;
	}
	*/

	// alang 2011-03-17覆盖
	function GetRow($sql,$forceprivate=false){
		$ret = $this->SelectLimit($sql,1,0,$forceprivate);
		if(!$ret)
			$this->Halt("执行SQL：".$sql."无法返回一个有效的数据集");
		$result = $ret->GetRow();
		return $result;
	}

	function GetAll($sql,$forceprivate=false) {
		$result = &$this->Execute($sql,0,$forceprivate);
		if($result){
			$arr = $result->GetAll();
			Return $arr;
		}
		Return false;
	}

	// 2011-03-10修改
	function GetAssoc($sql,$forceprivate=false) {
		$result = &$this->Execute($sql,0,$forceprivate);
		if($result){
                    $arr = array();
			while($r = $result->FetchRow()) {
				/*
				for($i=1;$i<count($r);$i++){
					$arr[$r[0]] = $arr[$r[$i]];

				}
				*/

				if(count($r) == 4){
					$arr[$r[0]] = $r[1];
				}else{
					$arr[$r[0]] = $r;
				}
			}
			if($arr){
				Return $arr;
			}else{
				Return false;
			}
		}
	}

	function Connection() {
		if ($this -> linkId == 0){
			if ($this -> pconnect){
				$this -> linkId = @mysql_pconnect($this->host,$this->user,$this->pass, true);
			}

			else{
				$this -> linkId = @mysql_connect($this->host,$this->user,$this->pass);
				
				//$this -> linkId = @mysql_connect($this->host,$this->user,$this->pass);
				
			
			}

			if (!$this -> linkId){
				$this -> Halt("登录数据库失败。",0);
				return false;
			}

			if (!is_null($this->database) && !@mysql_select_db($this->database,$this->linkId)){
				$this -> Halt("不能使用数据库：".$this -> database);
				return false;
			}

			if ($this -> CheckVersion() >= 4100){
				$sql = "SET NAMES '".$this->char."'";
				mysql_query($sql, $this->linkId);
			}

			if(is_array($this->server_reads)){
				if(sizeof($this->server_reads)>0){
						// @include_once DISCUZ_ROOT.'./include/slave_status.php';
						// $slave_status=&$slave_nj_status;

					foreach($this->server_reads as $key => $dbserver){
						if($slave_status[$key]==1){
							unset($this->server_reads[$key]);
						}
					}
				}

				if(sizeof($this->server_reads)>0){
					$rnd_key=$this->get_rnd_db_key();

					if($rnd_key!=-1){
						if($dbserver=$this->server_reads[$rnd_key]){
							$this->link_read_id=@mysql_connect($dbserver[name], $dbserver[user], $dbserver[password], 1);

							if($this->link_read_id){
								if ($this -> CheckVersion() >= 4100){
									$sql = "SET NAMES '".$this->char."'";
									mysql_query($sql, $this->link_read_id);
								}

								if($this->database!=""){
									if(!mysql_select_db($this->database, $this->link_read_id)){
										unset($this->link_read_id);
									}
								}
							}
						}

						if(!$this->link_read_id){
							unset($this->server_reads[$rnd_key]);
							if(sizeof($this->server_reads)==0) break;
						}
					}

				}
			}

			return $this -> linkId;
		}
	}

	function Halt($msg,$mysqlerr=0,$dieErr = true){
		$err = "数据库错误: $msg<br />";
		if($mysqlerr!=0)
			$err.= "MySQL 错误报告: [".$this->ErrorNo()."] ".$this->ErrorMsg()."\n";
		if(1===$this->dieMethod){
			$this->Errorlog .= $err;
			Return false;
		}
        if (ENVIRONMENT == 'production') {
            die('数据库错误');
        }
		die($err);
	}

	function ErrorMsg() {
		$err= @mysql_error($this -> linkId);
		Return $err;
	}

	function ErrorNo() {
		$err = @mysql_errno($this -> linkId);
		Return $err;
	}

	function CheckVersion(){
		$ret = mysql_get_server_info();
		$pieces = explode("-", $ret);
		$arr = preg_split('/\./',$pieces[0], -1,PREG_SPLIT_NO_EMPTY);
		$ret = $arr[0].$arr[1].$arr[2];
		$ret = (int)$ret;
		return $ret;
	}

	function GetMicTime(){
    	list($usec, $sec) = explode(" ",microtime());
    	return ((float)$usec + (float)$sec);
	}

	function Close(){
		
        if($this->linkId!=null)
        {
            mysql_close($this->linkId);
            unset($this);
        }
	}

	// add by tyb 2011-3-10
	function get_rnd_db_key() {
		$server_counts=0;

		foreach($this->server_reads as $value){
			$server_counts+=$value[weight];
		}

		$server_counts+=P_MASTER_WEIGHT;

		mt_srand((double) microtime()*1000000);
		$rnd_key=mt_rand(1,$server_counts);

		$rnd_flag=false;
		foreach($this->server_reads as $key => $value){
			if($rnd_key>$value[weight]){
				$rnd_key-=$value[weight];
				continue;
			}
			else{
				$rnd_key=$key;
				$rnd_flag=true;
				break;
			}
		}

		if($rnd_flag==false) $rnd_key=-1;

		return $rnd_key;
	}
}

######################### 数据集 ################################
class TINY_ADODB_ARRAY{
	var $datastore;
	var $curRow = 0;
	var $fetchMode;
	var $dieMethod;

	function TINY_ADODB_ARRAY(&$data,&$fetchMode,&$dieMethod){
		$this->datastore = &$data;
		$this->fetchMode = &$fetchMode;
		$this->dieMethod = &$dieMethod;
	}

	function CurrentRow() {
		Return false;
	}

	function GetArray(){
		$i=0;
                $result = array();
		while($row = mysql_fetch_array(&$this->datastore,$this->fetchMode)){
			$result[$i]=$row;
			$i++;
		}
		return $result;
	}

	function GetAll() {
		$arr = &$this->GetArray();
		Return $arr;
	}
	//后添加的方法
	function GetRow(){
		$arr = &$this->GetArray();
                if(!empty($arr)) {
		Return $arr[0];
                } else {
                    return array();
	}
	}

	function GetOne(){
		$row = $this->FetchArray();
                if(!empty($row)) {
		return $row[0];
                } else {
                    return null;
	}
	}

	function GetAssoc() {
		while($r = $this->FetchRow()) {
			/*
			for($i=1;$i<count($r);$i++){
				$arr[$r[0]] = $arr[$r[$i]];
			}
			*/

			if(count($r) == 4){
				$arr[$r[0]] = $r[1];
			}else{
				$arr[$r[0]] = $r;
			}
		}
		if($arr){
			Return $arr;
		}else{
			Return false;
		}
	}

	function FetchRow(){
		$row = &$this->FetchArray();
		return $row;
	}

	function FetchArray(){
		$row = mysql_fetch_array(&$this->datastore,$this->fetchMode);
		return $row;
	}

	function FetchObject(){
		$objrow = mysql_fetch_object(&$this->datastore);
		return $objrow;
	}

	function RecordCount(){
		$rscnt = mysql_num_rows(&$this->datastore);
		return $rscnt;
	}

	function RowCount() {
		$rscnt = $this->RecordCount();
		Return $rscnt;
	}

	function Affected_Rows(){
		$rscnt = mysql_affected_rows();
		return $rscnt;
	}

	function Move($rownum) {
		$status = @mysql_data_seek(&$this->datastore,$rownum);
		if($status){
			$this->curRow = $rownum;
			return true;
		}else{
			$this->Halt("Move[seek]($rownum)失败！数据集中共有".$this->RecordCount()."条记录。");
			@mysql_data_seek(&$this -> datastore,$this->RecordCount());
            $this -> curRow = $this->RecordCount();
            return false;

		}
	}

	function MoveFirst() {
		if($this->curRow==0) {
			Return true;
		}else{
			Return $this->Move(0);
		}
	}

	function MoveNext() {
		if($this->curRow<$this->RecordCount()-1) {
			$this->curRow++;
			Return $this-Move($this->curRow);
		}
		Return false;
	}

	function MoveLast() {
		if ($this->RecordCount() >= 0) return $this->Move($this->RecordCount()-1);
		Return false;
	}

	function FieldCount() {
		$cnt = mysql_num_fields(&$this->datastore);
		Return $cnt;
	}

	function FetchField($fieldoffset=0) {
		$meta = mysql_fetch_field(&$this->datastore,$fieldoffset);
		Return $meta;#obj
	}

	function FetchAllFields() {
		$i = 0;
		while ($i < $this->FieldCount($result)) {
		   $fieldObj[$i] = FetchField($i);
		   $i++;
		}
		Return $fieldObj;
	}

	function Halt($msg,$mysqlerr=0){
		$err = "数据库错误: $msg<br />";
		echo $err;
	}

	function Close(){
		mysql_free_result(&$this->datastore);
	}
}


/*
	缩略版ADODB(数据库操作类)
	文件名：class_adodb.php
    改动说明：数据库不提供创建链接
*/
class SIMPLE_DB {
	var $type = "mysql";
	var $host;
	var $user;
	var $pass;
	var $database;
	var $char = "utf8";
	var $linkId = 0;
	var $arr;
	var $debug;
	var $dieMethod = 2;###1:return false and continue; # 2:die Msg###
	var $costtime = array();
	var $fetchMode = MYSQL_BOTH;
	var $debuglog;

	// add by tyb 2011-3-10
	var $server_reads=array();
	var $link_read_ids=array();
        var $link_read_id = 0;
	var $forceprivateflag=false;

	// 增加参数 $server_reads: 读库; $forceprivateflag: 是否强制读取主库
	function SIMPLE_DB($type, $host = NULL, $user = NULL,$pass = NULL, $database = NULL,$char = NULL, $debug = NULL, $db_source = NULL) {
		if(!is_null($type)) $this->type=$type;
		if(!is_null($host)) $this->host=$host;
		if(!is_null($user)) $this->user=$user;
		if(!is_null($pass)) $this->pass=$pass;
		if(!is_null($database)) $this->database=$database;
		if(!is_null($char)) $this->char=$char;
		if(!is_null($debug))$this->debug = $debug;
        
        //if(!is_null($db_source)){
			$this->linkId = mysql_connect($this->host,$this->user,$this->pass) or die('数据库连接失败！');
            
			//$this->linkId = $db_source;

            if (!is_null($this->database) && !@mysql_select_db($this->database,$this->linkId)){
				$this -> Halt("不能使用数据库：".$this->database, 0);
			}

			if ($this -> CheckVersion() >= 4100){
				$sql = "SET NAMES '".$this->char."'";
				mysql_query($sql, $this->linkId);
			}
        /*}
		else
        {
            $this->Halt("登录数据库失败。", 0);
        }*/
	}

	function CheckLink($sql){
		if ($sql == '') return false;
		if (!$this -> linkId) return false;
		if ($this -> debug)
			$this->costtime && $this->costtime[0] = $this->GetMicTime();
	}

	function Insert_ID(){
		$insertId = mysql_insert_id($this->linkId);
		return $insertId;
	}

	function Affected_Rows() {
		return mysql_affected_rows($this->linkId);
	}

	function Execute($sql,$unbuffered=0,$forceprivate=false){
		$this->CheckLink($sql);

		if($unbuffered && $this->CheckVersion()>4060 && @function_exists('mysql_unbuffered_query')){
			$func = "mysql_unbuffered_query";
		}else{
			$func = "mysql_query";
		}

		$readfromprivate=true;
		if($forceprivate==false) $forceprivate=$this->forceprivateflag;

		if($this->link_read_id){
			if($forceprivate==false&&(substr(trim(strtoupper($sql)),0,6)=="SELECT")){
				$result=$func($sql,$this->link_read_id);
			}

			if($result) $readfromprivate=false;
		}

		if($readfromprivate==true){
			$result = @mysql_query($sql,$this -> linkId);
		}

		if($this->debug){
			$this->costtime[1] = $this->GetMicTime();
			$costtime = substr(($this->costtime[1]-$this->costtime[0])*1000,0,10);
			$this->debuglog .= "[Debug]\n执行：$sql\n花费：$costtime 毫秒\n时间：".date("Y-m-d H:i:s")."\n\n";
		}

		if($unbuffered){
			$ret = $result;
		}else{
			if($result==false) return false;
			$ret = new TINY_ADODB_ARRAY(&$result,$this->fetchMode,$this->dieMethod);
		}

		return $ret;
	}

	function SelectLimit($sql,$offset_b,$offset_n=0,$forceprivate=false){
		$this->CheckLink($sql);
		if(!$offset_n){
			$limit = " limit ".$offset_b;
		}else{
			$limit = " limit ".$offset_b.",".$offset_n;
		}
		$sql.=$limit;
		$result = $this->Execute($sql,$forceprivate);
		return $result;
	}

	function GetOne($sql,$forceprivate=false){
		$ret = $this->SelectLimit($sql,1,0,$forceprivate);
		if(!$ret)
			$this->Halt("执行SQL：".$sql."无法返回一个有效的数据集");
		$result = $ret->GetOne();
		return $result;
	}

	/*
	function GetRow($sql){
		$row = &$this->GetOne($sql);
		return $row;
	}
	*/

	// alang 2011-03-17覆盖
	function GetRow($sql,$forceprivate=false){
		$ret = $this->SelectLimit($sql,1,0,$forceprivate);
		if(!$ret)
			$this->Halt("执行SQL：".$sql."无法返回一个有效的数据集");
		$result = $ret->GetRow();
		return $result;
	}

	function GetAll($sql,$forceprivate=false) {
		$result = &$this->Execute($sql,0,$forceprivate);
		if($result){
			$arr = $result->GetAll();
			Return $arr;
		}
		Return false;
	}

	// 2011-03-10修改
	function GetAssoc($sql,$forceprivate=false) {
		$result = &$this->Execute($sql,0,$forceprivate);
		if($result){
                    $arr = array();
			while($r = $result->FetchRow()) {
				/*
				for($i=1;$i<count($r);$i++){
					$arr[$r[0]] = $arr[$r[$i]];

				}
				*/

				if(count($r) == 4){
					$arr[$r[0]] = $r[1];
				}else{
					$arr[$r[0]] = $r;
				}
			}
			if($arr){
				Return $arr;
			}else{
				Return false;
			}
		}
	}

	function Halt($msg,$mysqlerr=0,$dieErr = true){
		$err = "数据库错误: $msg<br />";
		if($mysqlerr!=0)
			$err.= "MySQL 错误报告: [".$this->ErrorNo()."] ".$this->ErrorMsg()."\n";
		if(1===$this->dieMethod){
			$this->Errorlog .= $err;
			Return false;
		}
        if (ENVIRONMENT == 'production') {
            die('数据库错误');
        }
		die($err);
	}

	function ErrorMsg() {
		$err= @mysql_error($this -> linkId);
		Return $err;
	}

	function ErrorNo() {
		$err = @mysql_errno($this -> linkId);
		Return $err;
	}

	function CheckVersion(){
		$ret = mysql_get_server_info();
		$pieces = explode("-", $ret);
		$arr = preg_split('/\./',$pieces[0], -1,PREG_SPLIT_NO_EMPTY);
		$ret = $arr[0].$arr[1].$arr[2];
		$ret = (int)$ret;
		return $ret;
	}

	function GetMicTime(){
    	list($usec, $sec) = explode(" ",microtime());
    	return ((float)$usec + (float)$sec);
	}

	function Close(){
        if($this->linkId!=null)
        {
            mysql_close($this->linkId);
            unset($this);
        }
	}

	// add by tyb 2011-3-10
	function get_rnd_db_key() {
		$server_counts=0;

		foreach($this->server_reads as $value){
			$server_counts+=$value[weight];
		}

		$server_counts+=P_MASTER_WEIGHT;

		mt_srand((double) microtime()*1000000);
		$rnd_key=mt_rand(1,$server_counts);

		$rnd_flag=false;
		foreach($this->server_reads as $key => $value){
			if($rnd_key>$value[weight]){
				$rnd_key-=$value[weight];
				continue;
			}
			else{
				$rnd_key=$key;
				$rnd_flag=true;
				break;
			}
		}

		if($rnd_flag==false) $rnd_key=-1;

		return $rnd_key;
	}
}
?>