<?php
/*******************************************************************
 * 版权协议：2009-2019
 * 版权所有: PHP-北京金南曦网络技术有限公司旗下PHPWMS，PHP商城系统技术支持中心http://www.php188.net，并保留所有权利。 
* PHP商城系统网址: http://www.php188.com
 * PHPWMS系统网址：http://www.phpwms.com
 * 销售电话：010-87875088
 * 销售电话：010-87875188 
*------------------------------------------------------------------
 * 这不是一个完全免费软件！您只能在不用于商业目的的前提下对程序代码进
 * 行修改和使用；不允许对程序代码以任何形式任何目的的再发布。
 *------------------------------------------------------------------
 * 文件名称：cls.db_mysql.php
 * 摘    要：MYSQL数据库类
 * 适用范围：MySQL 3.23+/4.0+/4.1+/5.0+
 * 版    本：1.0
 *------------------------------------------------------------------
 * Script Written By phpwms项目组
 * 最后更新： 2009-09-24 phpwms 由PHP金南曦网络技术有限公司整理发布
 *******************************************************************/

	if(!defined('IN_SYS')) die('Hacking attempt');
	include_once('cls.db_base.php');
	class DbMysql extends DbBase 
	{
		public  $mysql_version;
		public  $multi_insert = true;
		public  $queryLog = array();
		public  $showQuery = false;
		public  $_sql = '';
		private $_start = 0;
		public $querycount = 0;
		public $process = 0;
		private $_end = 0;
		private $_query_times = array();
		function getRunInfo(){
			return $this->querycount.' Querys in '.(!empty($this->_query_times)?array_sum($this->_query_times):0).' second(s)';
		}
		function __destruct(){
			$this->sql_freeresult($this->db_connect_id);
			return @mysql_close($this->db_connect_id);
		}
		
		/**
		* Connect to server
		* @access public
		*/
		function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
		{
			global $dbcharset;
			$this->persistency = $persistency;
			$this->user = $sqluser;
			$this->server = $sqlserver . (($port) ? ':' . $port : '');
			$this->dbname = $database;

			$this->sql_layer = 'mysql4';

			$func = $persistency == false ? 'mysql_connect' : 'mysql_pconnect';
			
			if ($this->db_connect_id = @$func($this->server, $this->user, $sqlpassword, $new_link)) {
				@$halt && $this->halt('Can not connect to MySQL server');
			}

			if ($this->db_connect_id && $this->dbname != '')
			{
				if (@mysql_select_db($this->dbname, $this->db_connect_id))
				{
					// Determine what version we are using and if it natively supports UNICODE
					$this->mysql_version = mysql_get_server_info($this->db_connect_id);
				    @mysql_query("set character_set_client = binary",$this->db_connect_id);
					@mysql_query("set character_set_connection = $dbcharset",$this->db_connect_id);
					@mysql_query("set character_set_database = $dbcharset",$this->db_connect_id);
					@mysql_query("set character_set_results = $dbcharset",$this->db_connect_id);
					@mysql_query("set character_set_server = $dbcharset",$this->db_connect_id);
					@mysql_query("set character_set_system = $dbcharset",$this->db_connect_id);
					if (version_compare($this->mysql_version, '4.1.3', '>='))
					{
			 			// enforce strict mode on databases that support it
						if (version_compare($this->mysql_version, '5.0.2', '>='))
						{
							$result = @mysql_query('SELECT @@session.sql_mode AS sql_mode', $this->db_connect_id);
							$row = @mysql_fetch_assoc($result);
							@mysql_free_result($result);
							$modes = array_map('trim', explode(',', $row['sql_mode']));

							// TRADITIONAL includes STRICT_ALL_TABLES and STRICT_TRANS_TABLES
							if (!in_array('TRADITIONAL', $modes))
							{
								if (!in_array('STRICT_ALL_TABLES', $modes))
								{
									$modes[] = 'STRICT_ALL_TABLES';
								}

								if (!in_array('STRICT_TRANS_TABLES', $modes))
								{
									$modes[] = 'STRICT_TRANS_TABLES';
								}
							}

							$mode = implode(',', $modes);
							@mysql_query("SET SESSION sql_mode='{$mode}'", $this->db_connect_id);
						}
					}
					else if (version_compare($this->mysql_version, '4.0.0', '<'))
					{
						$this->sql_layer = 'mysql';
					}

					return $this->db_connect_id;
				}
			}

			return $this->sql_error('');
		}
	function getLastInsertId(){
		return mysql_insert_id($this->db_connect_id);
	}
	function get_last_insert_id(){
		return $this->getLastInsertId();
	}
		/**
		* Version information about used database
		*/
		function sql_server_info()
		{
			return 'MySQL ' . $this->mysql_version;
		}

		/**
		* SQL Transaction
		* @access private
		*/
		function _sql_transaction($status = 'begin')
		{
			switch ($status)
			{
				case 'begin':
					return @mysql_query('BEGIN', $this->db_connect_id);
				break;

				case 'commit':
					return @mysql_query('COMMIT', $this->db_connect_id);
				break;

				case 'rollback':
					return @mysql_query('ROLLBACK', $this->db_connect_id);
				break;
			}

			return true;
		}
		function setQuery($sql){
			global $tbprefix;
			return $this->_sql = str_replace("##__",$tbprefix,$sql);
		}
		function insert($data = array(),$table,$insert = TRUE){
	   		$va = $this->_implodeArrayForInsert($data);
	   		$sql = "INSERT INTO ".'`'.$this->dbname.'`.'."`##__$table` $va";
	   		$this->setQuery($sql);
	   		return $insert?$this->query():$this->loadQuery();
	   	}
	private function _implodeArrayForUpdate($array){
		$comma = $info = '';
		if (is_array($array) && count($array)){
			foreach($array as $key=>$value) {
				$info .= "$comma`$key`".' = '."'$value'";
				$comma = ', ';
				}
			}
		return $info;
	}
	public function update($data,$table,$where = '',$do = true){
			if(!is_array($data))return false;
			if(count($data)<=0)return false;
			$value = $this->_implodeArrayForUpdate($data);
			$where = empty($where)?' ':' WHERE '.$this->_setWhere($where);#构造where字子句
			$sql   = "UPDATE `".$this->dbname."`.`##__$table` SET $value $where;";
			$this->setQuery($sql);
			return $do?$this->query():$this->loadQuery();
	}
	private function _setWhere($where){
		$comma = $info =  '';
		if (is_array($where) && count($where)){
			foreach($where as $key=>$value) {
				$info .= "$comma`$key`".' = '."'".$value."'";
				$comma = ' AND ';
				}
			}
		return $info;
	}
		 function _buildingInsertFiled($array,$loadfiled = true){
			if(!is_array($array))return $array;
			$tag = $field = $value = '';
			foreach ($array as $key=>$v){
				$field .= "$tag`".$key."`";
				$value .= "$tag'".$v."'";
				$tag = ' , ';
			}
			return $loadfiled?$field:$value;
		}
		function  _implodeArrayForInsert($array){
				if(!is_array($array))return FALSE;
				$result = '';
				if(!is_mulit_array($array)){
					$result  = '('.$this->_buildingInsertFiled($array).') VALUES ('.$this->_buildingInsertFiled($array,FALSE).');';
				}else{
					$tag = '';
					$first = '';
					$curent_array = current($array);
					$result .= '('.$this->_buildingInsertFiled($curent_array).') VALUES '."\n".'(';
					foreach ($array as $values){
						$result .= $tag.$first.$this->_buildingInsertFiled($values,FALSE);
						$tag = '),'; 
						$first  = '('; 
					}
					$result .= ');'; 
				}
				return $result;
		}
		function query($query = ''){
			$query = !empty($query)?$query:$this->_sql;
			return $this->sql_query($query);
		}
		/**
		* Base query method
		*
		* @param	string	$query		Contains the SQL query which shall be executed
		* @param	int		$cache_ttl	Either 0 to avoid caching or the time in seconds which the result shall be kept in cache
		* @return	mixed				When casted to bool the returned value returns true on success and false on failure
		*
		* @access	public
		*/
		function sql_query($query = ''){
				global $tbprefix;
				$query = empty($query)?$this->loadQuery():$query;
				$query = str_replace("##__",$tbprefix,$query);
				$this->setQuery($query);
				if(empty($query))exit('empty mysql query');
				if (defined('DEBUG_EXTRA'))
				{
					$this->sql_report('start', $query);
				}
					$this->_start = microtime_float();
					array_push($this->queryLog,$query);
					if($this->showQuery)return $query;
					if (($this->query_result = @mysql_query($query, $this->db_connect_id)) === false)
					{
						$this->sql_error($query);
					}else{
						$this->_end = microtime_float();
						array_push($this->_query_times,abs(number_format($this->_end-$this->_start,6)));
						++$this->querycount;
					}

					if (defined('DEBUG_EXTRA'))
					{
						$this->sql_report('stop', $query);
					}
			return ($this->query_result) ? $this->query_result : false;
		}
		function loadQueryLog(){
			return $this->queryLog;
		}
		function loadQuery(){
			return $this->_sql;
		}
		/**
		* Build LIMIT query
		*/
		function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) 
		{
			$this->query_result = false;

			// if $total is set to 0 we do not want to limit the number of rows
			if ($total == 0)
			{
				// Having a value of -1 was always a bug
				$total = '18446744073709551615';
			}

			$query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total);

			return $this->sql_query($query, $cache_ttl);
		}
		function fetch($sql,$one = false){
			$re  = $this -> sql_query($sql);
			$arr = $this -> sql_fetchrowset($re);
			return $one?$arr[0]:$arr;
		}

		/**
		* Return number of affected rows
		*/
		function sql_affectedrows()
		{
			return ($this->db_connect_id) ? @mysql_affected_rows($this->db_connect_id) : false;
		}

		/**
		* Fetch current row
		*/
		function sql_fetchrow($query_id = false)
		{
			global $cache;

			if ($query_id === false)
			{
				$query_id = $this->query_result;
			}

			if (isset($cache->sql_rowset[$query_id]))
			{
				return $cache->sql_fetchrow($query_id);
			}

			return ($query_id !== false) ? @mysql_fetch_assoc($query_id) : false;
		}

		/**
		* Seek to given row number
		* rownum is zero-based
		*/
		function sql_rowseek($rownum, &$query_id)
		{
			global $cache;

			if ($query_id === false)
			{
				$query_id = $this->query_result;
			}

			if (isset($cache->sql_rowset[$query_id]))
			{
				return $cache->sql_rowseek($rownum, $query_id);
			}

			return ($query_id !== false) ? @mysql_data_seek($query_id, $rownum) : false;
		}

		/**
		* Get last inserted id after insert statement
		*/
		function sql_nextid()
		{
			return ($this->db_connect_id) ? @mysql_insert_id($this->db_connect_id) : false;
		}

		/**
		* Free sql result
		*/
		function sql_freeresult($query_id = false)
		{
			global $cache;

			if ($query_id === false)
			{
				$query_id = $this->query_result;
			}

			if (isset($cache->sql_rowset[$query_id]))
			{
				return $cache->sql_freeresult($query_id);
			}

			if (isset($this->open_queries[(int) $query_id]))
			{
				unset($this->open_queries[(int) $query_id]);
				return @mysql_free_result($query_id);
			}

			return false;
		}

		/**
		* Escape string used in sql query
		*/
		function sql_escape($msg) {
			if (!$this -> db_connect_id) {
				return @mysql_real_escape_string($msg);
			}
			return @mysql_real_escape_string($msg, $this->db_connect_id);
		}

		/**
		* Build LIKE expression
		* @access private
		*/
		function _sql_like_expression($expression)
		{
			return $expression;
		}

		/**
		* Build db-specific query data
		* @access private
		*/
		function _sql_custom_build($stage, $data)
		{
			switch ($stage)
			{
				case 'FROM':
					$data = '(' . $data . ')';
				break;
			}

			return $data;
		}
		
		/**
		* return sql error array
		* @access private
		*/
		function _sql_error()
		{
			if (!$this->db_connect_id)
			{
				return array(
					'message'	=> @mysql_error(),
					'code'		=> @mysql_errno()
				);
			}

			return array(
				'message'	=> @mysql_error($this->db_connect_id),
				'code'		=> @mysql_errno($this->db_connect_id)
			);
		}

		/**
		* Close sql connection
		* @access private
		*/
		function _sql_close()
		{
			return @mysql_close($this->db_connect_id);
		}

		/**
		* Build db-specific report
		* @access private
		*/
		function _sql_report($mode, $query = '')
		{
			static $test_prof;

			// current detection method, might just switch to see the existance of INFORMATION_SCHEMA.PROFILING
			if ($test_prof === null)
			{
				$test_prof = false;
				if (strpos($this->mysql_version, 'community') !== false)
				{
					$ver = substr($this->mysql_version, 0, strpos($this->mysql_version, '-'));
					if (version_compare($ver, '5.0.37', '>=') && version_compare($ver, '5.1', '<'))
					{
						$test_prof = true;
					}
				}
			}

			switch ($mode)
			{
				case 'start':

					$explain_query = $query;
					if (preg_match('/UPDATE ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m))
					{
						$explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2];
					}
					else if (preg_match('/DELETE FROM ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m))
					{
						$explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2];
					}

					if (preg_match('/^SELECT/', $explain_query))
					{
						$html_table = false;

						// begin profiling
						if ($test_prof)
						{
							@mysql_query('SET profiling = 1;', $this->db_connect_id);
						}

						if ($result = @mysql_query("EXPLAIN $explain_query", $this->db_connect_id))
						{
							while ($row = @mysql_fetch_assoc($result))
							{
								$html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
							}
						}
						@mysql_free_result($result);

						if ($html_table)
						{
							$this->html_hold .= '</table>';
						}

						if ($test_prof)
						{
							$html_table = false;

							// get the last profile
							if ($result = @mysql_query('SHOW PROFILE ALL;', $this->db_connect_id))
							{
								$this->html_hold .= '<br />';
								while ($row = @mysql_fetch_assoc($result))
								{
									// make <unknown> HTML safe
									if (!empty($row['Source_function']))
									{
										$row['Source_function'] = str_replace(array('<', '>'), array('&lt;', '&gt;'), $row['Source_function']);
									}

									// remove unsupported features
									foreach ($row as $key => $val)
									{
										if ($val === null)
										{
											unset($row[$key]);
										}
									}
									$html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
								}
							}
							@mysql_free_result($result);

							if ($html_table)
							{
								$this->html_hold .= '</table>';
							}

							@mysql_query('SET profiling = 0;', $this->db_connect_id);
						}
					}

				break;

				case 'fromcache':
					$endtime = explode(' ', microtime());
					$endtime = $endtime[0] + $endtime[1];

					$result = @mysql_query($query, $this->db_connect_id);
					while ($void = @mysql_fetch_assoc($result))
					{
						// Take the time spent on parsing rows into account
					}
					@mysql_free_result($result);

					$splittime = explode(' ', microtime());
					$splittime = $splittime[0] + $splittime[1];

					$this->sql_report('record_fromcache', $query, $endtime, $splittime);

				break;
			}
		}
	}
?>