<?php
/**************************************************
*  Created:  2010-06-08
*
*  MysqlDB类
*
*  @Xweibo (C)1996-2099 SINA Inc.
*  @Author xuzhenquan <zhenquan@staff.sina.com.cn>
*
***************************************************/

if (!class_exists('interface_db')) {
	require('interface_db.php');
}
class mysql_db extends interface_db 
{
	var $table = ''; // default table name
	var $last_sql = ''; // last query sql
	var $querys = array(); // query history
	var $auto_free = false; // switch of auto free result 
	var $last_query_id = false; // query id
	var $prefix = ''; // 表名前缀
	var $params = array(); // db params
	/**
	 * contructor
	 * @param $table default table name
	 * @return void
	 */
	function mysql_db() {
	}

	function getPrefix() {
		return $this->prefix;
	}
	function adp_init($params) {
		$this->params = $params;
		$this->prefix = $params['tbpre'];
	}
	
	function setTable($table) {
		$this->table = $table;
	}
	
	/**
	 * get table name
	 * @param $table_name string tablename
	 * @param $tb_prefix sting prefix of table
	 * @return string
	 */
	function getTable($table_name='', $tb_prefix='') {
		if (empty($tb_prefix)) {
			$tb_prefix = $this->getPrefix();
		}
		$table_name = trim($table_name);
		$table_name = $table_name == ''? $this->table : $table_name;
		return $tb_prefix . $table_name;
	}
	
	function pushSql($sql) {
		array_push($this->querys, $sql);
		return $this->last_sql = $sql;
	}

	/**
	 * set auto free query result
	 *
	 */
	function setAutoFree($v) {
		$this->autoFree = (bool)$v;
	}
	/**
	 * return escape value
	 * @param $str string
	 * @return string
	 */
	function escape($str) {
		return mysql_escape_string($str);
	}

	/**
	 * return mysql insert id
	 */
	function getInsertId() {
		return mysql_insert_id($this->getWriteConnect());
	}
	/**
	 * get info by row id
	 * @param $id int query row id
	 * @param $table string table name
	 * @param $id_name string field name(primary key)
	 */
	function get($id, $table='', $id_name = 'id') {
		$id = (int)$id;
		if ($id <=0 || !($table = $this->getTable($table))) {
			return false;
		}

		$sql = 'SELECT *FROM ' . $table . ' WHERE ' .$id_name . ' = ' .(int)$id;
		$this->execute($sql);
		if (!$this->last_query_id) {
			return false;
		}
		$rst =  mysql_fetch_array($this->last_query_id);
		if (!$rst) {
			return array();
		}
		if ($this->autoFree) {
			$this->free();
		}
		return $rst;
	}
	
	/**
	 * delete info
	 * @param $id int|array row id
	 * @param $table string table name
	 * @param $id_name string field name(primary key)
	 * @return int|false 
	 */
	function delete($id, $table = '', $id_name = 'id') {
		if (!$table = $this->getTable($table)) {
			return false;
		}
		if (!is_array($id)) {
			$id = (array)$id;
		}
		foreach ($id as $o) {
			if ((int)$o <= 0) {
				return false;
			}
		}
		$sql = 'DELETE FROM ' . $table . ' WHERE ' . $id_name . ' IN(' . implode(',', $id). ')';
		if (!$this->execute($sql)) {
			return false;
		}
		return $this->getAffectedRows();
	}
	
	/**
	 * insert or update table
	 * @param $data key/value array data
	 * @param $id int update id
	 * @param $table string table name
	 * @param $id_name string field name(primary key)
	 * @return int|false lastinsert id or update id
	 */
	function save($data, $id = '', $table = '', $id_name = 'id') {
		if ($id == '') {
			$type = 'insert';
		} else {
			$type = 'update';
		}
		$table = $this->getTable($table);
		if ($type == 'insert') {
			$keys = array();
			$values = array();
			foreach ($data as $key => $value) {
				$keys[] = '`' .$key . '`';
				$values[] = '"' .mysql_escape_string($value) . '"';
			}
			if (sizeof($keys) != sizeof($values)) {
				return false;
			}
			$sql = 'INSERT INTO ' . $table . '(' .implode(',', $keys). ') VALUES('. implode(',', $values) .')';
			if (!$this->execute($sql)) {
				return false;
			}
			return $this->getInsertId();
		}
		$values = array();
		foreach ($data as $key=>$value) {
			$values[] = '`' .trim($key) . '`="' . mysql_escape_string($value) . '"';
		}
		if (!sizeof($values)) {
			return false;
		}
		$sql = 'UPDATE ' . $table . ' SET ' . implode(',', $values) . ' WHERE ' . $id_name . '=' . $id;
		
		if (!$this->execute($sql)) {
			return false;
		}
		return $this->getAffectedRows();
	}
	
	function getReadConnect($index = null) {
		static $connect = null;
		if ($connect === null) {
			if (!isset($this->params['slaves']) || empty($this->params['slaves'])) {
				return $this->getWriteConnect();
			}
			$count = count($this->params['slaves']);
			$n = $count > 1 ? rand(0, count($this->params['slaves'])-1): 0;
			$p = $this->params['slaves'][$n];
			if (!(isset($p['host']) && isset($p['user']) && isset($p['pwd']))) {
				return $this->getWriteConnect();
			}
			if (!isset($p['port'])) {
				$p['port'] = 3306;
			}
			$connect = mysql_connect($p['host'] . ':' . $p['port'], $p['user'], $p['pwd']);
			$p['db'] = isset($p['db']) ? $p['db'] : $this->params['db'];
			$p['charset'] = isset($p['charset']) ? $p['charset'] : $this->params['charset'];
			mysql_select_db($p['db'], $connect);
			mysql_query('SET NAMES ' . $p['charset'], $connect);
		}
		return $connect;
	}

	function getWriteConnect() {
		static $connect = null;
		if ($connect === null) {
			if (!isset($this->params) || empty($this->params)) {
				return false;
			}
			extract($this->params);
			if (!(isset($host) && isset($user) && isset($pwd))) {
				return false;
			}
			if (!isset($port)) {
				$port = 3306;
			}
			$connect = mysql_connect($host . ':' . $port, $user, $pwd);
			mysql_select_db($db, $connect);
			mysql_query('SET NAMES ' . $charset, $connect);
		}
		return $connect;
	}

	function getConnect($sql = null) {
		$write_command = array('insert', 'update', 'delete', 'replace', 'alter', 'create', 'drop', 'rename', 'truncate');
		if ($sql !== null) {
			$sql = explode(' ', trim((string)$sql));
		}
		if ($sql === null || !in_array(strtolower($sql[0]), $write_command)) {
			return $this->getReadConnect();
		}
		return $this->getWriteConnect();
	}

	/**
	 * execute sql
	 * @param $sql string SQL
	 * @return void
	 */
	function execute($sql) {
		$sql = $this->pushSql($sql);
		$this->last_query_id = mysql_query($sql, $this->getConnect($sql));
		if ($this->last_query_id) {
			return $this->last_query_id;
		}
		return false;
	}
	
	/**
	 * 
	 * @return int affected rows
	 */
	function getAffectedRows() {
		return mysql_affected_rows($this->getWriteConnect());
	}
	
	/**
	 * execute SQL and return result
	 * @param $sql string SQL
	 * @return array
	 */
	function query($sql) {
		if (!$this->execute($sql)) {
			return false;
		}
		$data = array();
		while ($row = mysql_fetch_array($this->last_query_id)) {
			$data[] = $row;
		}

		if ($this->autoFree) {
			$this->free();
		}
		return $data;
	}
	/**
	 * return the first field of a row
	 * @param $sql string SQL
	 * @return mixed
	 */
	function getOne($sql, $index=0) {
		if (!$this->execute($sql)) {
			return false;
		}
		$rst = mysql_fetch_row($this->last_query_id);
		if ($this->autoFree) {
			$this->free();
		}
		if (!$rst) {
			return array();
		}
		return $rst[(int)$index];
	}

	/**
	 * retun a row
	 * @param $sql string SQL
	 * @param array
	 */
	function getRow($sql) {
			if (!$this->execute($sql)) {
			return false;
		}
		$rst = mysql_fetch_array($this->last_query_id);
		if (!$rst) {
			return array();
		}
		if ($this->autoFree) {
			$this->free();
		}
		return $rst;
	}
	
	/**
	 * return last query SQL
	 * @return string last query SQL
	 */
	function getLastQuery() {
		return $this->last_sql;
	}

	function getError() {
		return mysql_error($this->getConnect());
	}
	
	/**
	 * free query result
	 * @param int query handle
	 */
	function free($query_id=""){
		if ($query_id == "") $query_id = $this->last_query_id;
		if ($query_id == '') {
			return;
		}
		mysql_free_result($query_id);
		$this->last_query_id = '';
    	}

	/**
	 * close mysql connection
	 */
	function close() {
		mysql_close($this->getConnect());
	}
	
	/**
	 * return query history SQL
	 * @return array
	 */
	function getHistory() {
		return $this->querys;
	}
}

