|
|
<?php
|
|
|
class LtDbHandle
|
|
|
{
|
|
|
public $configHandle;
|
|
|
public $group;
|
|
|
public $node;
|
|
|
public $role = "master";
|
|
|
public $connectionAdapter;
|
|
|
public $connectionResource;
|
|
|
public $sqlAdapter;
|
|
|
protected $connectionManager;
|
|
|
private $servers;
|
|
|
|
|
|
public function __construct()
|
|
|
{
|
|
|
}
|
|
|
|
|
|
public function init()
|
|
|
{
|
|
|
if(empty($this->servers))
|
|
|
{
|
|
|
$this->servers = $this->configHandle->get("db.servers");
|
|
|
}
|
|
|
$this->connectionManager = new LtDbConnectionManager;
|
|
|
$this->connectionManager->configHandle = $this->configHandle;
|
|
|
$this->sqlAdapter = $this->getCurrentSqlAdapter();
|
|
|
$connectionInfo = $this->connectionManager->getConnection($this->group, $this->node, $this->role);
|
|
|
$this->connectionAdapter = $connectionInfo["connectionAdapter"];
|
|
|
$this->connectionResource = $connectionInfo["connectionResource"];
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Trancaction methods
|
|
|
*/
|
|
|
public function beginTransaction()
|
|
|
{
|
|
|
return $this->connectionAdapter->exec($this->sqlAdapter->beginTransaction(), $this->connectionResource);
|
|
|
}
|
|
|
|
|
|
public function commit()
|
|
|
{
|
|
|
return $this->connectionAdapter->exec($this->sqlAdapter->commit(), $this->connectionResource);
|
|
|
}
|
|
|
|
|
|
public function rollBack()
|
|
|
{
|
|
|
return $this->connectionAdapter->exec($this->sqlAdapter->rollBack(), $this->connectionResource);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Execute an sql query
|
|
|
*
|
|
|
* @param $sql
|
|
|
* @param $bind
|
|
|
* @param $forceUseMaster
|
|
|
* @return false on query failed
|
|
|
* --sql type-- --return value--
|
|
|
* SELECT, SHOW, DESECRIBE, EXPLAIN rowset or NULL when no record found
|
|
|
* INSERT the ID generated for an AUTO_INCREMENT column
|
|
|
* UPDATE, DELETE, REPLACE affected count
|
|
|
* USE, DROP, ALTER, CREATE, SET etc true
|
|
|
* @notice 每次只能执行一条SQL
|
|
|
* 不要通过此接口执行USE DATABASE, SET NAMES这样的语句
|
|
|
*/
|
|
|
public function query($sql, $bind = null, $forceUseMaster = false)
|
|
|
{
|
|
|
$sql = trim($sql);
|
|
|
if (empty($sql))
|
|
|
{
|
|
|
trigger_error('Empty the SQL statement');
|
|
|
}
|
|
|
$queryType = $this->sqlAdapter->detectQueryType($sql);
|
|
|
switch ($queryType)
|
|
|
{
|
|
|
case "SELECT":
|
|
|
if (!$forceUseMaster && isset($this->servers[$this->group][$this->node]["slave"]))
|
|
|
{
|
|
|
$this->role = "slave";
|
|
|
}
|
|
|
$queryMethod = "select";
|
|
|
break;
|
|
|
case "INSERT":
|
|
|
$this->role = "master";
|
|
|
$queryMethod = "insert";
|
|
|
break;
|
|
|
case "CHANGE_ROWS":
|
|
|
$this->role = "master";
|
|
|
$queryMethod = "changeRows";
|
|
|
break;
|
|
|
case "SET_SESSION_VAR":
|
|
|
$queryMethod = "setSessionVar";
|
|
|
break;
|
|
|
case "OTHER":
|
|
|
default:
|
|
|
$this->role = "master";
|
|
|
$queryMethod = "other";
|
|
|
break;
|
|
|
}
|
|
|
$connectionInfo = $this->connectionManager->getConnection($this->group, $this->node, $this->role);
|
|
|
$this->connectionAdapter = $connectionInfo["connectionAdapter"];
|
|
|
$this->connectionResource = $connectionInfo["connectionResource"];
|
|
|
if (is_array($bind) && 0 < count($bind))
|
|
|
{
|
|
|
$sql = $this->bindParameter($sql, $bind);
|
|
|
}
|
|
|
return $this->$queryMethod($sql, $this->connectionResource);
|
|
|
}
|
|
|
/**
|
|
|
* function posted by renlu
|
|
|
*/
|
|
|
public function escape($str)
|
|
|
{
|
|
|
return $this->connectionAdapter->escape($str, $this->connectionResource);
|
|
|
}
|
|
|
/**
|
|
|
* function posted by renlu
|
|
|
*/
|
|
|
public function insertid()
|
|
|
{
|
|
|
return $this->connectionAdapter->lastInsertId($this->connectionResource);
|
|
|
}
|
|
|
/**
|
|
|
* Generate complete sql from sql template (with placeholder) and parameter
|
|
|
*
|
|
|
* @param $sql
|
|
|
* @param $parameter
|
|
|
* @return string
|
|
|
* @todo 兼容pgsql等其它数据库,pgsql的某些数据类型不接受单引号引起来的值
|
|
|
*/
|
|
|
public function bindParameter($sql, $parameter)
|
|
|
{
|
|
|
// 注意替换结果尾部加一个空格
|
|
|
$sql = preg_replace("/:([a-zA-Z0-9_\-\x7f-\xff][a-zA-Z0-9_\-\x7f-\xff]*)\s*([,\)]?)/", "\x01\x02\x03\\1\x01\x02\x03\\2 ", $sql);
|
|
|
foreach($parameter as $key => $value)
|
|
|
{
|
|
|
$find[] = "\x01\x02\x03$key\x01\x02\x03";
|
|
|
if ($value instanceof LtDbSqlExpression)
|
|
|
{
|
|
|
$replacement[] = $value->__toString();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
$replacement[] = "'" . $this->connectionAdapter->escape($value, $this->connectionResource) . "'";
|
|
|
}
|
|
|
}
|
|
|
$sql = str_replace($find, $replacement, $sql);
|
|
|
return $sql;
|
|
|
}
|
|
|
|
|
|
protected function getCurrentSqlAdapter()
|
|
|
{
|
|
|
$factory = new LtDbAdapterFactory;
|
|
|
$host = key($this->servers[$this->group][$this->node][$this->role]);
|
|
|
return $factory->getSqlAdapter($this->servers[$this->group][$this->node][$this->role][$host]["sql_adapter"]);
|
|
|
}
|
|
|
|
|
|
protected function select($sql, $connResource)
|
|
|
{
|
|
|
$result = $this->connectionAdapter->query($sql, $connResource);
|
|
|
if (empty($result))
|
|
|
{
|
|
|
return null;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
return $result;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
protected function insert($sql, $connResource)
|
|
|
{
|
|
|
if ($result = $this->connectionAdapter->exec($sql, $connResource))
|
|
|
{
|
|
|
return $this->connectionAdapter->lastInsertId($connResource);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
return $result;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
protected function changeRows($sql, $connResource)
|
|
|
{
|
|
|
return $this->connectionAdapter->exec($sql, $connResource);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
* @todo 更新连接缓存
|
|
|
*/
|
|
|
protected function setSessionVar($sql, $connResource)
|
|
|
{
|
|
|
return false === $this->connectionAdapter->exec($sql, $connResource) ? false : true;
|
|
|
}
|
|
|
|
|
|
protected function other($sql, $connResource)
|
|
|
{
|
|
|
return false === $this->connectionAdapter->exec($sql, $connResource) ? false : true;
|
|
|
}
|
|
|
}
|