<?php
/*
* Copyright (c) 2018, 北京博习园教育科技有限公司
* All rights reserved.
*
* 文件名称: xmodel.php
* 摘 要: 模型公共类
* 作 者: 刘泉皓
* $Id$
*/ /**
* 数据库连接类,依赖 PDO_MYSQL 扩展
* walkor:在 https://github.com/auraphp/Aura.SqlQuery 的基础上修改而成
* liuquanhao:在 https://github.com/walkor/mysql 的基础上修改而成
*/ require_once __DIR__ . '/' . '../../../config/config.php';
require_once __DIR__ . '/' . '../function/cache.php';
require_once __DIR__ . '/' . '../function/comm_func.php'; class XModel
{
/**
* SELECT
*
* @var array
*/
protected $union = array(); /**
* 是否是更新
*
* @var bool
*/
protected $for_update = false; /**
* 选择的列
*
* @var array
*/
protected $cols = array(); /**
* 从哪些表里面 SELECT
*
* @var array
*/
protected $from = array(); /**
* $from 当前的 key
*
* @var int
*/
protected $from_key = -1; /**
* GROUP BY 的列
*
* @var array
*/
protected $group_by = array(); /**
* HAVING 条件数组.
*
* @var array
*/
protected $having = array(); /**
* HAVING 语句中绑定的值.
*
* @var array
*/
protected $bind_having = array(); /**
* 每页多少条记录
*
* @var int
*/
protected $paging = 10; /**
* sql 中绑定的值
*
* @var array
*/
protected $bind_values = array(); /**
* WHERE 条件.
*
* @var array
*/
protected $where = array(); /**
* WHERE 语句绑定的值
*
* @var array
*/
protected $bind_where = array(); /**
* ORDER BY 的列
*
* @var array
*/
protected $order_by = array(); /**
* ORDER BY 的排序方式,默认为升序
*
* @var bool
*/
protected $order_asc = true;
/**
* SELECT 多少记录
*
* @var int
*/
protected $limit = 0; /**
* 返回记录的游标
*
* @var int
*/
protected $offset = 0; /**
* flags 列表
*
* @var array
*/
protected $flags = array(); /**
* 操作哪个表
*
* @var string
*/
protected $table; /**
* 表.列 和 last-insert-id 映射
*
* @var array
*/
protected $last_insert_id_names = array(); /**
* INSERT 或者 UPDATE 的列
*
* @param array
*/
protected $col_values; /**
* 返回的列
*
* @var array
*/
protected $returning = array(); /**
* sql 的类型 SELECT INSERT DELETE UPDATE
*
* @var string
*/
protected $type = ''; /**
* pdo 实例
*
* @var PDO
*/
protected $pdo; /**
* PDOStatement 实例
*
* @var PDOStatement
*/
protected $sQuery; /**
* 数据库用户名密码等配置
*
* @var array
*/
protected $readSettings = array();
protected $writeSettings = array(); /**
* sql 的参数
*
* @var array
*/
protected $parameters = array(); /**
* 最后一条直行的 sql
*
* @var string
*/
protected $lastSql = ''; /**
* 使用memcache
*
* @var object
*/
protected $mem = null;
/**
* memcache key
*
* @var string
*/
protected $memKey = '';
/**
* memcache active time
*
* @var int
*/
protected $memTime = 0;
/**
* log
*
* @var boolean
*/
protected $log = false;
protected $logName = __CLASS__; /**
* 是否执行成功
*
* @var bool
*/
protected $success = false; /**
* 构造函数
*/
public function __construct($dbname = '')
{
if (!empty($dbname)) {
$this->database($dbname);
} // 使用惰性连接
//$this->connect();
} /*
* 选择数据库
*/
public function database($dbname)
{
switch ($dbname) {
case 'tongzhuo_ask_db':
$this->selectAskHost();
break;
case 'tongzhuonet_db':
$this->selectTznetHost();
break;
case 'tongzhuo_weixin_db':
$this->selectWeixinHost();
break;
case 'tongzhuo_user_db':
$this->selectUserHost();
break;
case 'tongzhuo_examination_db':
$this->selectExaminationHost();
break;
case 'tongzhuo_tv_db':
$this->selectTvHost();
break;
case 'tongzhuo_db':
$this->selectTzHost();
break;
default:
throw new Exception('Not found database!');
}
return $this;
} /*
* 使用memcache
*/
public function mem($key = '', $activeTime = 0)
{
global $mem;
$this->mem = $mem;
$this->memKey = $key;
$this->memTime = $activeTime;
return $this;
} /**
* 选择哪些列
*
* @param string|array $cols
* @return self
*/
public function select($cols = '*')
{
$this->type = 'SELECT';
if (!is_array($cols)) {
$cols = explode(',', $cols);
}
$this->cols($cols);
return $this;
} /**
* 从哪个表删除
*
* @param string $table
* @return self
*/
public function delete($table)
{
$this->type = 'DELETE';
$this->table = $this->quoteName($table);
$this->fromRaw($this->quoteName($table));
return $this;
} /**
* 从哪个表hash删除
*
* @param string $pre
* @param string $salt
* @return self
*/
public function deleteHash($pre, $salt)
{
$table = $this->hashTable($pre, $salt);
return $this->delete($table);
} /**
* 更新哪个表
*
* @param string $table
* @return self
*/
public function update($table)
{
$this->type = 'UPDATE';
$this->table = $this->quoteName($table);
return $this;
} /**
* 更新哪个hash表
*
* @param string $pre
* @param string $salt
* @return self
*/
public function updateHash($pre, $salt)
{
$table = $this->hashTable($pre, $salt);
return $this->update($table);
} /**
* 向哪个表插入
*
* @param string $table
* @return self
*/
public function insert($table)
{
$this->type = 'INSERT';
$this->table = $this->quoteName($table);
return $this;
} /**
* 向哪个hash表插入
*
* @param string $pre
* @param string $hash
* @return self
*/
public function insertHash($pre, $salt)
{
$table = $this->hashTable($pre, $salt);
return $this->insert($table);
} /**
* from 哪个表
*
* @param string $table
* @return self
*/
public function from($table)
{
return $this->fromRaw($this->quoteName($table));
} /**
* from 哪个hash表
*
* @param string $pre
* @param string $salt
* @return self
*/
public function fromHash($pre, $salt)
{
$table = $this->hashTable($pre, $salt);
return $this->from($table);
} /**
* from的表
*
* @param string $table
* @return self
*/
public function fromRaw($table)
{
$this->from[] = array($table);
$this->from_key++;
return $this;
} /**
*
* 子查询
*
* @param string $table
* @param string $name The alias name for the sub-select.
* @return self
*/
public function fromSubSelect($table, $name)
{
$this->from[] = array("($table) AS " . $this->quoteName($name));
$this->from_key++;
return $this;
} /**
* 增加 join 语句
*
* @param string $table
* @param string $cond
* @param string $type
* @return self
* @throws Exception
*/
public function join($table, $cond = null, $type = '')
{
return $this->joinInternal($type, $table, $cond);
} /**
* 增加 join 语句
*
* @param string $join inner, left, natural
* @param string $table
* @param string $cond
* @return self
* @throws Exception
*/
protected function joinInternal($join, $table, $cond = null)
{
if (!$this->from) {
throw new Exception('Cannot join() without from()');
} $join = strtoupper(ltrim("$join JOIN"));
$table = $this->quoteName($table);
$cond = $this->fixJoinCondition($cond);
$this->from[$this->from_key][] = rtrim("$join $table $cond");
return $this;
} /**
* left join
*
* @param string $table
* @param string $cond
* @return self
* @throws Exception
*/
public function leftJoin($table, $cond = null)
{
return $this->joinInternal('LEFT', $table, $cond);
} /**
* right join
*
* @param string $table
* @param string $cond
* @return self
* @throws Exception
*/
public function rightJoin($table, $cond = null)
{
return $this->joinInternal('RIGHT', $table, $cond);
} /**
* joinSubSelect
*
* @param string $join inner, left, natural
* @param string $spec
* @param string $name sub-select 的别名
* @param string $cond
* @return self
* @throws Exception
*/
public function joinSubSelect($join, $spec, $name, $cond = null)
{
if (!$this->from) {
throw new Exception('Cannot join() without from() first.');
} $join = strtoupper(ltrim("$join JOIN"));
$name = $this->quoteName($name);
$cond = $this->fixJoinCondition($cond);
$this->from[$this->from_key][] = rtrim("$join ($spec) AS $name $cond");
return $this;
} /**
* group by 语句
*
* @param array $cols
* @return self
*/
public function groupBy(array $cols)
{
foreach ($cols as $col) {
$this->group_by[] = $this->quoteNamesIn($col);
}
return $this;
} /**
* having 语句
*
* @param string $cond
* @return self
*/
public function having($cond)
{
$this->addClauseCondWithBind('having', 'AND', func_get_args());
return $this;
} /**
* or having 语句
*
* @param string $cond The HAVING condition.
* @return self
*/
public function orHaving($cond)
{
$this->addClauseCondWithBind('having', 'OR', func_get_args());
return $this;
} /*
* 重连tv读写数据库
*/
protected function selectTvHost()
{
$this->readSettings['user'] = $GLOBALS['user_tv_read'];
$this->readSettings['password'] = $GLOBALS['pw_tv_read'];
$this->readSettings['host'] = $GLOBALS['host_tv_read'];
$this->readSettings['port'] = $GLOBALS['port_tv_read'];
$this->readSettings['dbname'] = $GLOBALS['database_tv_read'];
$this->writeSettings['user'] = $GLOBALS['user_tv_write'];
$this->writeSettings['password'] = $GLOBALS['pw_tv_write'];
$this->writeSettings['host'] = $GLOBALS['host_tv_write'];
$this->writeSettings['port'] = $GLOBALS['port_tv_write'];
$this->writeSettings['dbname'] = $GLOBALS['database_tv_write'];
} /*
* 重连ask读写数据库
*/
protected function selectAskHost()
{
$this->readSettings['user'] = $GLOBALS['user_ask_read'];
$this->readSettings['password'] = $GLOBALS['pw_ask_read'];
$this->readSettings['host'] = $GLOBALS['host_ask_read'];
$this->readSettings['port'] = $GLOBALS['port_ask_read'];
$this->readSettings['dbname'] = $GLOBALS['database_ask_read'];
$this->writeSettings['user'] = $GLOBALS['user_ask_write'];
$this->writeSettings['password'] = $GLOBALS['pw_ask_write'];
$this->writeSettings['host'] = $GLOBALS['host_ask_write'];
$this->writeSettings['port'] = $GLOBALS['port_ask_write'];
$this->writeSettings['dbname'] = $GLOBALS['database_ask_write'];
}
/*
* 重连net读写数据库
*/
protected function selectTznetHost()
{
$this->readSettings['user'] = $GLOBALS['user_tz_read'];
$this->readSettings['password'] = $GLOBALS['pw_tz_read'];
$this->readSettings['host'] = $GLOBALS['host_tz_read'];
$this->readSettings['port'] = $GLOBALS['port_tz_read'];
$this->readSettings['dbname'] = $GLOBALS['database_tz_read'];
$this->writeSettings['user'] = $GLOBALS['user_tz_write'];
$this->writeSettings['password'] = $GLOBALS['pw_tz_write'];
$this->writeSettings['host'] = $GLOBALS['host_tz_write'];
$this->writeSettings['port'] = $GLOBALS['port_tz_write'];
$this->writeSettings['dbname'] = $GLOBALS['database_tz_write'];
}
/*
* 重连weixin读写数据库
*/
protected function selectWeixinHost()
{
$this->readSettings['user'] = $GLOBALS['user_wx_read'];
$this->readSettings['password'] = $GLOBALS['pw_wx_read'];
$this->readSettings['host'] = $GLOBALS['host_wx_read'];
$this->readSettings['port'] = $GLOBALS['port_wx_read'];
$this->readSettings['dbname'] = $GLOBALS['database_wx_read'];
$this->writeSettings['user'] = $GLOBALS['user_wx_write'];
$this->writeSettings['password'] = $GLOBALS['pw_wx_write'];
$this->writeSettings['host'] = $GLOBALS['host_wx_write'];
$this->writeSettings['port'] = $GLOBALS['port_wx_write'];
$this->writeSettings['dbname'] = $GLOBALS['database_wx_write'];
}
/*
* 重连用户日志读写数据库
*/
protected function selectUserHost()
{
$this->readSettings['user'] = $GLOBALS['user_user_read'];
$this->readSettings['password'] = $GLOBALS['pw_user_read'];
$this->readSettings['host'] = $GLOBALS['host_user_read'];
$this->readSettings['port'] = $GLOBALS['port_user_read'];
$this->readSettings['dbname'] = $GLOBALS['database_user_read'];
$this->writeSettings['user'] = $GLOBALS['user_user_write'];
$this->writeSettings['password'] = $GLOBALS['pw_user_write'];
$this->writeSettings['host'] = $GLOBALS['host_user_write'];
$this->writeSettings['port'] = $GLOBALS['port_user_write'];
$this->writeSettings['dbname'] = $GLOBALS['database_user_write'];
}
/*
* 模拟考试读写数据库
*/
protected function selectExaminationHost()
{
$this->readSettings['user'] = $GLOBALS['user_ex_read'];
$this->readSettings['password'] = $GLOBALS['pw_ex_read'];
$this->readSettings['host'] = $GLOBALS['host_ex_read'];
$this->readSettings['port'] = $GLOBALS['port_ex_read'];
$this->readSettings['dbname'] = $GLOBALS['database_ex_read'];
$this->writeSettings['user'] = $GLOBALS['user_user_write'];
$this->writeSettings['password'] = $GLOBALS['pw_ex_write'];
$this->writeSettings['host'] = $GLOBALS['host_ex_write'];
$this->writeSettings['port'] = $GLOBALS['port_ex_write'];
$this->writeSettings['dbname'] = $GLOBALS['database_ex_write'];
}
/*
* 重连tongzhuo读写数据库
*/
protected function selectTzHost()
{
$this->readSettings['user'] = $GLOBALS['user_one_read'];
$this->readSettings['password'] = $GLOBALS['pw_one_read'];
$this->readSettings['host'] = $GLOBALS['host_one_read'];
$this->readSettings['port'] = $GLOBALS['port_one_read'];
$this->readSettings['dbname'] = $GLOBALS['database_one_read'];
$this->writeSettings['user'] = $GLOBALS['user_one_write'];
$this->writeSettings['password'] = $GLOBALS['pw_one_write'];
$this->writeSettings['host'] = $GLOBALS['host_one_write'];
$this->writeSettings['port'] = $GLOBALS['port_one_write'];
$this->writeSettings['dbname'] = $GLOBALS['database_one_write'];
} /**
* 创建 PDO 实例
*/
protected function connect()
{
if ($this->type == 'SELECT') {
if (
empty($this->readSettings['dbname']) &&
empty($this->readSettings['host']) &&
empty($this->readSettings['port']) &&
empty($this->readSettings['user']) &&
empty($this->readSettings['password'])) {
throw new Exception('Database configuration fail!');
}
$dsn = 'mysql:dbname=' . $this->readSettings['dbname'] .
';host=' . $this->readSettings['host'] . ';port=' . $this->readSettings['port'] .
';charset=utf8';
$this->pdo = new PDO(
$dsn,
$this->readSettings['user'],
$this->readSettings['password']
);
} else {
if (
empty($this->writeSettings['dbname']) &&
empty($this->writeSettings['host']) &&
empty($this->writeSettings['port']) &&
empty($this->writeSettings['user']) &&
empty($this->writeSettings['password'])) {
throw new Exception('Database configuration fail!');
}
$dsn = 'mysql:dbname=' . $this->writeSettings['dbname'] .
';host=' . $this->writeSettings['host'] . ';port=' . $this->writeSettings['port'] .
';charset=utf8';
$this->pdo = new PDO(
$dsn,
$this->writeSettings['user'],
$this->writeSettings['password']
);
}
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
$this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} /*
* 清空本次mem设置信息
*/
protected function resetMem()
{
$this->mem = null;
$this->memKey = '';
$this->memTime = 0;
} /**
* 关闭连接
*/
public function closeConnection()
{
$this->pdo = null;
}
/**
*
* 设置 SQL_CALC_FOUND_ROWS 标记.
*
* @param bool $enable
* @return self
*/
public function calcFoundRows($enable = true)
{
$this->setFlag('SQL_CALC_FOUND_ROWS', $enable);
return $this;
} /**
* 设置 SQL_CACHE 标记
*
* @param bool $enable
* @return self
*/
public function cache($enable = true)
{
$this->setFlag('SQL_CACHE', $enable);
return $this;
} /**
* 设置 SQL_NO_CACHE 标记
*
* @param bool $enable
* @return self
*/
public function noCache($enable = true)
{
$this->setFlag('SQL_NO_CACHE', $enable);
return $this;
} /**
* 设置 STRAIGHT_JOIN 标记.
*
* @param bool $enable
* @return self
*/
public function straightJoin($enable = true)
{
$this->setFlag('STRAIGHT_JOIN', $enable);
return $this;
} /**
* 设置 HIGH_PRIORITY 标记
*
* @param bool $enable
* @return self
*/
public function highPriority($enable = true)
{
$this->setFlag('HIGH_PRIORITY', $enable);
return $this;
} /**
* 设置 SQL_SMALL_RESULT 标记
*
* @param bool $enable
* @return self
*/
public function smallResult($enable = true)
{
$this->setFlag('SQL_SMALL_RESULT', $enable);
return $this;
} /**
* 设置 SQL_BIG_RESULT 标记
*
* @param bool $enable
* @return self
*/
public function bigResult($enable = true)
{
$this->setFlag('SQL_BIG_RESULT', $enable);
return $this;
} /**
* 设置 SQL_BUFFER_RESULT 标记
*
* @param bool $enable
* @return self
*/
public function bufferResult($enable = true)
{
$this->setFlag('SQL_BUFFER_RESULT', $enable);
return $this;
} /**
* 设置 DISTINCT 标记
*
* @param bool $enable
* @return self
*/
public function distinct($enable = true)
{
$this->setFlag('DISTINCT', $enable);
return $this;
} /**
* 设置 LOW_PRIORITY 标记
*
* @param bool $enable
* @return self
*/
public function lowPriority($enable = true)
{
$this->setFlag('LOW_PRIORITY', $enable);
return $this;
} /**
* 设置 IGNORE 标记
*
* @param bool $enable
* @return self
*/
public function ignore($enable = true)
{
$this->setFlag('IGNORE', $enable);
return $this;
} /**
* 设置 QUICK 标记
*
* @param bool $enable
* @return self
*/
public function quick($enable = true)
{
$this->setFlag('QUICK', $enable);
return $this;
} /**
* 设置 DELAYED 标记
*
* @param bool $enable
* @return self
*/
public function delayed($enable = true)
{
$this->setFlag('DELAYED', $enable);
return $this;
} /**
* 设置 FOR UPDATE 标记
*
* @param bool $enable
* @return self
*/
public function forUpdate($enable = true)
{
$this->for_update = (bool) $enable;
return $this;
} /**
* 设置每页多少条记录
*
* @param int $paging
* @return self
*/
public function setPaging($paging)
{
$this->paging = (int) $paging;
return $this;
} /**
* 获取每页多少条记录
*
* @return int
*/
public function getPaging()
{
return $this->paging;
} /**
* 序列化
*
* @return string
*/
public function __toString()
{
$union = '';
if ($this->union) {
$union = implode(' ', $this->union) . ' ';
}
return $union . $this->build();
} /**
* 获取绑定在占位符上的值
*/
public function getBindValues()
{
switch ($this->type) {
case 'SELECT':
return $this->getBindValuesSELECT();
case 'DELETE':
case 'UPDATE':
case 'INSERT':
return $this->getBindValuesCOMMON();
default:
throw new Exception("type err");
}
} /**
* 获取绑定在占位符上的值
*
* @return array
*/
public function getBindValuesSELECT()
{
$bind_values = $this->bind_values;
$i = 1;
foreach ($this->bind_where as $val) {
$bind_values[$i] = $val;
$i++;
}
foreach ($this->bind_having as $val) {
$bind_values[$i] = $val;
$i++;
}
return $bind_values;
} /**
*
* SELECT选择哪些列
*
* @param mixed $key
* @param string $val
* @return void
*/
protected function addColSELECT($col, $alias)
{
if (is_string($col)) {
$this->cols[$alias] = $col;
} else {
$this->addColWithAlias($alias);
}
} /**
* SELECT 增加选择的列
*
* @param string $spec
*/
protected function addColWithAlias($spec)
{
$parts = explode(' ', trim($spec));
$count = count($parts);
if ($count == 2) {
$this->cols[$parts[1]] = $parts[0];
} elseif ($count == 3 && strtoupper($parts[1]) == 'AS') {
$this->cols[$parts[2]] = $parts[0];
} else {
$this->cols[] = $spec;
}
} /**
* quote
*
* @param string $cond
* @return string
*
*/
protected function fixJoinCondition($cond)
{
if (!$cond) {
return '';
} $cond = $this->quoteNamesIn($cond); if (strtoupper(substr(ltrim($cond), 0, 3)) == 'ON ') {
return $cond;
} if (strtoupper(substr(ltrim($cond), 0, 6)) == 'USING ') {
return $cond;
} return 'ON ' . $cond;
} /**
* inner join
*
* @param string $table
* @param string $cond
* @return self
* @throws Exception
*/
public function innerJoin($table, $cond = null)
{
return $this->joinInternal('INNER', $table, $cond);
}
/**
* 设置每页的记录数量
*
* @param int $page
* @return self
*/
public function page($page)
{
$this->limit = 0;
$this->offset = 0; $page = (int) $page;
if ($page > 0) {
$this->limit = $this->paging;
$this->offset = $this->paging * ($page - 1);
}
return $this;
} /**
* union
*
* @return self
*/
public function union()
{
$this->union[] = $this->build() . ' UNION';
$this->reset();
return $this;
} /**
* unionAll
*
* @return self
*/
public function unionAll()
{
$this->union[] = $this->build() . ' UNION ALL';
$this->reset();
return $this;
} /**
* 重置
*/
protected function reset()
{
$this->resetFlags();
$this->cols = array();
$this->from = array();
$this->from_key = -1;
$this->where = array();
$this->group_by = array();
$this->having = array();
$this->order_by = array();
$this->limit = 0;
$this->offset = 0;
$this->for_update = false;
} /**
* 清除所有数据
*/
protected function resetAll()
{
$this->union = array();
$this->for_update = false;
$this->cols = array();
$this->from = array();
$this->from_key = -1;
$this->group_by = array();
$this->having = array();
$this->bind_having = array();
$this->paging = 10;
$this->bind_values = array();
$this->where = array();
$this->bind_where = array();
$this->order_by = array();
$this->limit = 0;
$this->offset = 0;
$this->flags = array();
$this->table = '';
$this->last_insert_id_names = array();
$this->col_values = array();
$this->returning = array();
$this->parameters = array();
} /**
* 创建 SELECT SQL
*
* @return string
*/
protected function buildSELECT()
{
return 'SELECT'
. $this->buildFlags()
. $this->buildCols()
. $this->buildFrom()
. $this->buildWhere()
. $this->buildGroupBy()
. $this->buildHaving()
. $this->buildOrderBy()
. $this->buildLimit()
. $this->buildForUpdate();
} /**
* 创建 DELETE SQL
*/
protected function buildDELETE()
{
return 'DELETE'
. $this->buildFlags()
. $this->buildFrom()
. $this->buildWhere()
. $this->buildOrderBy()
. $this->buildLimit()
. $this->buildReturning();
} /**
* 生成 SELECT 列语句
*
* @return string
* @throws Exception
*/
protected function buildCols()
{
if (!$this->cols) {
throw new Exception('No columns in the SELECT.');
} $cols = array();
foreach ($this->cols as $key => $val) {
if (is_int($key)) {
$cols[] = $this->quoteNamesIn($val);
} else {
$cols[] = $this->quoteNamesIn("$val AS $key");
}
} return $this->indentCsv($cols);
} /**
* 生成 FROM 语句.
*
* @return string
*/
protected function buildFrom()
{
if (!$this->from) {
return '';
} $refs = array();
foreach ($this->from as $from) {
$refs[] = implode(' ', $from);
}
return ' FROM' . $this->indentCsv($refs);
} /**
* 生成 GROUP BY 语句.
*
* @return string
*/
protected function buildGroupBy()
{
if (!$this->group_by) {
return '';
}
return ' GROUP BY' . $this->indentCsv($this->group_by);
} /**
* 生成 HAVING 语句.
*
* @return string
*/
protected function buildHaving()
{
if (!$this->having) {
return '';
}
return ' HAVING' . $this->indent($this->having);
} /**
* 生成 FOR UPDATE 语句
*
* @return string
*/
protected function buildForUpdate()
{
if (!$this->for_update) {
return '';
}
return ' FOR UPDATE';
} /**
* where
*
* @param string|array $cond
* @return self
*/
public function where($cond)
{
if (is_array($cond)) {
foreach ($cond as $key => $val) {
if (is_string($key)) {
$this->addWhere('AND', array($key, $val));
} else {
$this->addWhere('AND', array($val));
}
}
} else {
$this->addWhere('AND', func_get_args());
}
return $this;
} /**
* or where
*
* @param string|array $cond
* @return self
*/
public function orWhere($cond)
{
if (is_array($cond)) {
foreach ($cond as $key => $val) {
if (is_string($key)) {
$this->addWhere('OR', array($key, $val));
} else {
$this->addWhere('OR', array($val));
}
}
} else {
$this->addWhere('OR', func_get_args());
}
return $this;
} /**
* limit
*
* @param int $limit
* @return self
*/
public function limit($limit)
{
$this->limit = (int) $limit;
return $this;
} /**
* limit offset
*
* @param int $offset
* @return self
*/
public function offset($offset)
{
$this->offset = (int) $offset;
return $this;
} /**
* orderby.
*
* @param array $cols
* @return self
*/
public function orderBy(array $cols)
{
return $this->addOrderBy($cols);
} /**
* order by ASC OR DESC
*
* @param array $cols
* @param bool $order_asc
* @return self
*/
public function orderByASC(array $cols, $order_asc = true)
{
$this->order_asc = $order_asc;
return $this->addOrderBy($cols);
} /**
* order by DESC
*
* @param array $cols
* @return self
*/
public function orderByDESC(array $cols)
{
$this->order_asc = false;
return $this->addOrderBy($cols);
} // -------------abstractquery----------
/**
* 返回逗号分隔的字符串
*
* @param array $list
* @return string
*/
protected function indentCsv(array $list)
{
return ' ' . implode(',', $list);
} /**
* 返回空格分隔的字符串
*
* @param array $list
* @return string
*/
protected function indent(array $list)
{
return ' ' . implode(' ', $list);
} /**
* 批量为占位符绑定值
*
* @param array $bind_values
* @return self
*
*/
public function bindValues(array $bind_values)
{
foreach ($bind_values as $key => $val) {
$this->bindValue($key, $val);
}
return $this;
} /**
* 单个为占位符绑定值
*
* @param string $name
* @param mixed $value
* @return self
*/
public function bindValue($name, $value)
{
$this->bind_values[$name] = $value;
return $this;
} /**
* 生成 flag
*
* @return string
*/
protected function buildFlags()
{
if (!$this->flags) {
return '';
}
return ' ' . implode(' ', array_keys($this->flags));
} /**
* 设置 flag.
*
* @param string $flag
* @param bool $enable
*/
protected function setFlag($flag, $enable = true)
{
if ($enable) {
$this->flags[$flag] = true;
} else {
unset($this->flags[$flag]);
}
} /**
* 重置 flag
*/
protected function resetFlags()
{
$this->flags = array();
} /**
*
* 添加 where 语句
*
* @param string $andor 'AND' or 'OR
* @param array $conditions
* @return self
*
*/
protected function addWhere($andor, $conditions)
{
$this->addClauseCondWithBind('where', $andor, $conditions);
return $this;
} /**
* 添加条件和绑定值
*
* @param string $clause where 、having等
* @param string $andor AND、OR等
* @param array $conditions
*/
protected function addClauseCondWithBind($clause, $andor, $conditions)
{
$cond = array_shift($conditions);
$cond = $this->quoteNamesIn($cond); $bind = &$this->{"bind_{$clause}"};
foreach ($conditions as $value) {
$bind[] = $value;
} $clause = &$this->$clause;
if ($clause) {
$clause[] = "$andor $cond";
} else {
$clause[] = $cond;
}
} /**
* 生成 where 语句
*
* @return string
*/
protected function buildWhere()
{
if (!$this->where) {
return '';
}
return ' WHERE' . $this->indent($this->where);
} /**
* 增加 order by
*
* @param array $spec The columns and direction to order by.
* @return self
*/
protected function addOrderBy(array $spec)
{
foreach ($spec as $col) {
$this->order_by[] = $this->quoteNamesIn($col);
}
return $this;
} /**
* 生成 order by 语句
*
* @return string
*/
protected function buildOrderBy()
{
if (!$this->order_by) {
return '';
} if ($this->order_asc) {
return ' ORDER BY' . $this->indentCsv($this->order_by) . ' ASC';
} else {
return ' ORDER BY' . $this->indentCsv($this->order_by) . ' DESC';
}
} /**
* 生成 limit 语句
*
* @return string
*/
protected function buildLimit()
{
$has_limit = $this->type == 'DELETE' || $this->type == 'UPDATE';
$has_offset = $this->type == 'SELECT'; if ($has_offset && $this->limit) {
$clause = " LIMIT {$this->limit}";
if ($this->offset) {
$clause .= " OFFSET {$this->offset}";
}
return $clause;
} elseif ($has_limit && $this->limit) {
return " LIMIT {$this->limit}";
}
return '';
} /**
* Quotes
*
* @param string $spec
* @return string|array
*/
public function quoteName($spec)
{
$spec = trim($spec);
$seps = array(' AS ', ' ', '.');
foreach ($seps as $sep) {
$pos = strripos($spec, $sep);
if (false !== $pos) {
return $this->quoteNameWithSeparator($spec, $sep, $pos);
}
}
return $this->replaceName($spec);
} /**
* 指定分隔符的 Quotes
*
* @param string $spec
* @param string $sep
* @param int $pos
* @return string
*/
protected function quoteNameWithSeparator($spec, $sep, $pos)
{
$len = strlen($sep);
$part1 = $this->quoteName(substr($spec, 0, $pos));
$part2 = $this->replaceName(substr($spec, $pos + $len));
return "{$part1}{$sep}{$part2}";
} /**
* Quotes "table.col" 格式的字符串
*
* @param string $text
* @return string|array
*/
public function quoteNamesIn($text)
{
$list = $this->getListForQuoteNamesIn($text);
$last = count($list) - 1;
$text = null;
foreach ($list as $key => $val) {
if (($key + 1) % 3) {
$text .= $this->quoteNamesInLoop($val, $key == $last);
}
}
return $text;
} /**
* 返回 quote 元素列表
*
* @param string $text
* @return array
*/
protected function getListForQuoteNamesIn($text)
{
$apos = "'";
$quot = '"';
return preg_split(
"/(($apos+|$quot+|\\$apos+|\\$quot+).*?\\2)/",
$text,
-1,
PREG_SPLIT_DELIM_CAPTURE
);
} /**
* 循环 quote
*
* @param string $val
* @param bool $is_last
* @return string
*/
protected function quoteNamesInLoop($val, $is_last)
{
if ($is_last) {
return $this->replaceNamesAndAliasIn($val);
}
return $this->replaceNamesIn($val);
} /**
* 替换成别名
*
* @param string $val
* @return string
*/
protected function replaceNamesAndAliasIn($val)
{
$quoted = $this->replaceNamesIn($val);
$pos = strripos($quoted, ' AS ');
if ($pos !== false) {
$alias = $this->replaceName(substr($quoted, $pos + 4));
$quoted = substr($quoted, 0, $pos) . " AS $alias";
}
return $quoted;
} /**
* Quotes name
*
* @param string $name
* @return string
*/
protected function replaceName($name)
{
$name = trim($name);
if ($name == '*') {
return $name;
}
return '`' . $name . '`';
} /**
* Quotes
*
* @param string $text
* @return string|array
*/
protected function replaceNamesIn($text)
{
$is_string_literal = strpos($text, "'") !== false
|| strpos($text, '"') !== false;
if ($is_string_literal) {
return $text;
} $word = '[a-z_][a-z0-9_]*'; $find = "/(\\b)($word)\\.($word)(\\b)/i"; $repl = '$1`$2`.`$3`$4'; $text = preg_replace($find, $repl, $text); return $text;
} // ---------- insert --------------
/**
* 设置 `table.column` 与 last-insert-id 的映射
*
* @param array $last_insert_id_names
*/
public function setLastInsertIdNames(array $last_insert_id_names)
{
$this->last_insert_id_names = $last_insert_id_names;
} /**
* insert into.
*
* @param string $table
* @return self
*/
public function into($table)
{
$this->table = $this->quoteName($table);
return $this;
} /**
* 生成 INSERT 语句
*
* @return string
*/
protected function buildINSERT()
{
return 'INSERT'
. $this->buildFlags()
. $this->buildInto()
. $this->buildValuesForInsert()
. $this->buildReturning();
} /**
* 生成 INTO 语句
*
* @return string
*/
protected function buildInto()
{
return " INTO " . $this->table;
} /**
* PDO::lastInsertId()
*
* @param string $col
* @return mixed
*/
public function getLastInsertIdName($col)
{
$key = str_replace('`', '', $this->table) . '.' . $col;
if (isset($this->last_insert_id_names[$key])) {
return $this->last_insert_id_names[$key];
} return null;
} /**
* 设置一列,如果有第二各参数,则把第二个参数绑定在占位符上
*
* @param string $col
* @return self
*/
public function col($col)
{
return call_user_func_array(array($this, 'addCol'), func_get_args());
} /**
* 设置多列
*
* @param array $cols
* @return self
*/
public function cols(array $cols)
{
if ($this->type == 'SELECT') {
foreach ($cols as $key => $val) {
$this->addColSELECT($key, $val);
}
return $this;
}
return $this->addCols($cols);
} /**
* 直接设置列的值
*
* @param string $col
* @param string $value
* @return self
*/
public function set($col, $value)
{
return $this->setCol($col, $value);
} /**
* 为 INSERT 语句绑定值
*
* @return string
*/
protected function buildValuesForInsert()
{
return ' (' . $this->indentCsv(array_keys($this->col_values)) . ') VALUES (' .
$this->indentCsv(array_values($this->col_values)) . ')';
} // ------update-------
/**
* 更新哪个表
*
* @param string $table
* @return self
*/
public function table($table)
{
$this->table = $this->quoteName($table);
return $this;
} /**
* 生成完整 SQL 语句
*
* @return string
* @throws Exception
*/
protected function build()
{
switch ($this->type) {
case 'DELETE':
return $this->buildDELETE();
case 'INSERT':
return $this->buildINSERT();
case 'UPDATE':
return $this->buildUPDATE();
case 'SELECT':
return $this->buildSELECT();
}
throw new Exception("type empty");
} /**
* 生成更新的 SQL 语句
*/
protected function buildUPDATE()
{
return 'UPDATE'
. $this->buildFlags()
. $this->buildTable()
. $this->buildValuesForUpdate()
. $this->buildWhere()
. $this->buildOrderBy()
. $this->buildLimit()
. $this->buildReturning();
} /**
* 哪个表
*
* @return string
*/
protected function buildTable()
{
return " {$this->table}";
} /**
* 为更新语句绑定值
*
* @return string
*/
protected function buildValuesForUpdate()
{
$values = array();
foreach ($this->col_values as $col => $value) {
$values[] = "{$col} = {$value}";
}
return ' SET' . $this->indentCsv($values);
} // ----------Dml---------------
/**
* 获取绑定的值
*
* @return array
*/
public function getBindValuesCOMMON()
{
$bind_values = $this->bind_values;
$i = 1;
foreach ($this->bind_where as $val) {
$bind_values[$i] = $val;
$i++;
}
return $bind_values;
} /**
* 设置列
*
* @param string $col
* @return self
*/
protected function addCol($col)
{
$key = $this->quoteName($col);
$this->col_values[$key] = ":$col";
$args = func_get_args();
if (count($args) > 1) {
$this->bindValue($col, $args[1]);
}
return $this;
} /**
* 设置多个列
*
* @param array $cols
* @return self
*/
protected function addCols(array $cols)
{
foreach ($cols as $key => $val) {
if (is_int($key)) {
$this->addCol($val);
} else {
$this->addCol($key, $val);
}
}
return $this;
} /**
* 设置单列的值
*
* @param string $col .
* @param string $value
* @return self
*/
protected function setCol($col, $value)
{
if ($value === null) {
$value = 'NULL';
} $key = $this->quoteName($col);
$value = $this->quoteNamesIn($value);
$this->col_values[$key] = $value;
return $this;
} /**
* 增加返回的列
*
* @param array $cols
* @return self
*
*/
protected function addReturning(array $cols)
{
foreach ($cols as $col) {
$this->returning[] = $this->quoteNamesIn($col);
}
return $this;
} /**
* 生成 RETURNING 语句
*
* @return string
*/
protected function buildReturning()
{
if (!$this->returning) {
return '';
}
return ' RETURNING' . $this->indentCsv($this->returning);
} /**
* 执行
*
* @param string $query
* @param string $parameters
* @throws PDOException
*/
protected function execute($query, $parameters = "")
{
try {
$this->connect();
$this->sQuery = @$this->pdo->prepare($query);
$this->bindMore($parameters);
if (!empty($this->parameters)) {
foreach ($this->parameters as $param) {
$parameters = explode("\x7F", $param);
$this->sQuery->bindParam($parameters[0], $parameters[1]);
}
}
$this->success = $this->sQuery->execute();
} catch (PDOException $e) {
// 服务端断开时重连一次
if ($e->errorInfo[1] == 2006 || $e->errorInfo[1] == 2013) {
$this->closeConnection();
try {
$this->connect();
$this->sQuery = $this->pdo->prepare($query);
$this->bindMore($parameters);
if (!empty($this->parameters)) {
foreach ($this->parameters as $param) {
$parameters = explode("\x7F", $param);
$this->sQuery->bindParam($parameters[0], $parameters[1]);
}
}
$this->success = $this->sQuery->execute();
} catch (PDOException $ex) {
$this->rollBackTrans();
throw $ex;
}
} else {
$this->rollBackTrans();
$msg = $e->getMessage();
$err_msg = "SQL:" . $this->lastSQL() . " " . $msg;
$exception = new PDOException($err_msg, (int) $e->getCode());
throw $exception;
}
}
if ($this->log) {
$message = sprintf("%s|%s", $query, implode(',', $this->parameters));
comm_log($this->logName, $message);
}
$this->parameters = array();
} /**
* 绑定
*
* @param string $para
* @param string $value
*/
public function bind($para, $value)
{
if (is_string($para)) {
$this->parameters[sizeof($this->parameters)] = ":" . $para . "\x7F" . $value;
} else {
$this->parameters[sizeof($this->parameters)] = $para . "\x7F" . $value;
}
} /**
* 绑定多个
*
* @param array $parray
*/
public function bindMore($parray)
{
if (empty($this->parameters) && is_array($parray)) {
$columns = array_keys($parray);
foreach ($columns as $i => &$column) {
$this->bind($column, $parray[$column]);
}
}
} /**
* 执行 SQL
*
* @param string $query
* @param array $params
* @param int $fetchmode
* @return mixed
*/
public function query($query = '', $params = null, $fetchmode = PDO::FETCH_ASSOC)
{
$query = trim($query);
if (empty($query)) {
$query = $this->build();
if (!$params) {
$params = $this->getBindValues();
}
} else {
$this->parseType($query);
}
$this->resetAll();
$this->lastSql = $query;
if ($this->type == 'SELECT' && $this->mem) {
if (empty($this->memKey)) {
$this->memKey = $query . ' [' . implode(',', $params) . ']';
} $buf = $this->mem->get($this->memKey);
if ($buf !== false) {
$this->resetMem();
return $buf;
}
}
$this->execute($query, $params);
$rawStatement = explode(" ", $query);
$statement = strtolower(trim($rawStatement[0]));
if ($statement === 'select' || $statement === 'show') {
$rs = $this->sQuery->fetchAll($fetchmode);
if ($statement === 'select' && $this->mem) {
$this->mem->set($this->memKey, $rs, 0, $this->memTime);
$this->resetMem();
}
return $rs;
} elseif ($statement === 'update' || $statement === 'delete') {
return $this->sQuery->rowCount();
} elseif ($statement === 'insert') {
if ($this->sQuery->rowCount() > 0) {
return $this->lastInsertId();
}
} else {
return null;
} return null;
} /**
* 返回一列
*
* @param string $query
* @param array $params
* @return array
*/
public function column($query = '', $params = null)
{
$query = trim($query);
if (empty($query)) {
$query = $this->build();
if (!$params) {
$params = $this->getBindValues();
}
}
$this->resetAll();
$this->lastSql = $query;
if ($this->mem) {
if (empty($this->memKey)) {
$this->memKey = $query . ' [' . implode(',', $params) . ']';
} $buf = $this->mem->get($this->memKey);
if ($buf !== false) {
$this->resetMem();
return $buf;
}
}
if (empty($this->type)) {
$this->parseType($query);
}
$this->execute($query, $params);
$columns = $this->sQuery->fetchAll(PDO::FETCH_NUM);
$column = null;
foreach ($columns as $cells) {
$column[] = $cells[0];
}
if ($this->mem) {
$this->mem->set($this->memKey, $column, 0, $this->memTime);
$this->resetMem();
}
return $column;
} /**
* 返回一行
*
* @param string $query
* @param array $params
* @param int $fetchmode
* @return array
*/
public function row($query = '', $params = null, $fetchmode = PDO::FETCH_ASSOC)
{
$query = trim($query);
if (empty($query)) {
$query = $this->build();
if (!$params) {
$params = $this->getBindValues();
}
} $this->resetAll();
$this->lastSql = $query;
if ($this->mem) {
if (empty($this->memKey)) {
$this->memKey = $query . ' [' . implode(',', $params) . ']';
}
$buf = $this->mem->get($this->memKey);
if ($buf !== false) {
$this->resetMem();
return $buf;
}
}
if (empty($this->type)) {
$this->parseType($query);
}
$this->execute($query, $params);
$rs = $this->sQuery->fetch($fetchmode);
if ($this->mem) {
$this->mem->set($this->memKey, $rs, 0, $this->memTime);
$this->resetMem();
}
return $rs;
} /**
* 返回单个值
*
* @param string $query
* @param array $params
* @return string
*/
public function single($query = '', $params = null)
{
$query = trim($query);
if (empty($query)) {
$query = $this->build();
if (!$params) {
$params = $this->getBindValues();
}
}
$this->resetAll();
if ($this->mem) {
if (empty($this->memKey)) {
$this->memKey = $query . ' [' . implode(',', $params) . ']';
}
$buf = $this->mem->get($this->memKey);
if ($buf !== false) {
$this->resetMem();
return $buf;
}
}
if (empty($this->type)) {
$this->parseType($query);
}
$this->execute($query, $params);
$rs = $this->sQuery->fetchColumn();
if ($this->mem) {
$this->mem->set($this->memKey, $rs, 0, $this->memTime);
$this->resetMem();
}
return $rs;
} /**
* 返回 lastInsertId
*
* @return string
*/
public function lastInsertId()
{
return $this->pdo->lastInsertId();
} /**
* 返回最后一条执行的 sql
*
* @return string
*/
public function lastSQL()
{
return $this->lastSql;
} /**
* 开始事务
*/
public function beginTrans()
{
try {
return $this->pdo->beginTransaction();
} catch (PDOException $e) {
// 服务端断开时重连一次
if ($e->errorInfo[1] == 2006 || $e->errorInfo[1] == 2013) {
$this->closeConnection();
$this->connect();
return $this->pdo->beginTransaction();
} else {
throw $e;
}
}
} /**
* 提交事务
*/
public function commitTrans()
{
return $this->pdo->commit();
} /**
* 事务回滚
*/
public function rollBackTrans()
{
if ($this->pdo) {
if ($this->pdo->inTransaction()) {
return $this->pdo->rollBack();
}
}
return true;
} /**
* hash分表
*/
protected function hashTable($pre, $salt)
{
if (empty($salt)) {
return $pre . '0';
} $salt = strtolower($salt);
if (is_numeric($salt) && strlen($salt) > 1) {
$hash = substr($salt, -2, 2);
} else if (preg_match("/^[0-9a-z]{1}$/", substr($salt, -1, 1))) {
$hash = substr($salt, -1, 1);
} else {
return $pre . '0';
}
return $pre . $hash;
} public function log($logName = '')
{
$this->log = true;
if (!empty($logName)) {
$this->logName = $logName;
}
return $this;
} /**
* 没有设置type,也不是select(),update(),insert(),delete()方法,则分析sql语句,设置type
*/
public function parseType($query)
{
$query = trim($query);
if (empty($query)) {
$this->type = 'SELECT';
}
$this->type = strtoupper(explode(' ', $query)[0]);
}
/**
* (废弃,已自动判断)
* SELECT:读库
* 其他:写库
*/
public function setType($type) {
$this->type = strtoupper($type);
}
}

PDO连接数据库-Xmodel的更多相关文章

  1. 【转】php pdo连接数据库 解决中文乱码问题(wordpress mysql 问号?? ??)

    原文链接:http://blog.csdn.net/ysydao/article/details/11002295 PHP 用pdo连接数据库时出现中文乱码问题解决办法 1.array(PDO::MY ...

  2. PDO连接数据库

    PDO连接数据库 PDO简介和配置 php.ini extension=php_pdo.dll extension=php_pdo_myysql.dll PDO连接MYSQL new PDO(&quo ...

  3. 使用PDO连接数据库 查询和插入乱码的解决方法

    问题:PDO连接数据库后,查询和插入中文到数据库,出现乱码,如图: 解决方法: 法1: try{ $opts_values = array(PDO::MYSQL_ATTR_INIT_COMMAND=& ...

  4. PHP5中使用PDO连接数据库的方法

    PDO(PHP Data Object) 是PHP 中加入的东西,是PHP 5新加入的一个重大功能,因为在PHP 5以前的php4/php3都是一堆的数据库扩展来跟各个数据库的连接和处理,php_my ...

  5. php PDO连接数据库

    [PDO是啥] PDO是PHP 5新加入的一个重大功能,因为在PHP 5以前的php4/php3都是一堆的数据库扩展来跟各个数据库的连接和处理,什么 php_mysql.dll.php_pgsql.d ...

  6. php+mysql+pdo连接数据库

    1.$pdo = new PDO("mysql:host=localhost;dbname=test","root","123456");/ ...

  7. 封装PDO连接数据库代码

    废话不说直接上代码: <?php class DB { protected static $_connect; protected $dsn, $pdo; protected $_data, $ ...

  8. 使用PDO连接数据库

    PDO(PHP数据对象) 是一个轻量级的.具有兼容接口的PHP数据连接拓展,是一个PHP官方的PECL库,随PHP 5.1发布,需要PHP 5的面向对象支持,因而在更早的版本上无法使用.它所提供的数据 ...

  9. pdo 连接数据库 报错 could not find driver 解决方法

    在windows 下,调试一个PHP程序时,报了这个错误, could not find driver 原来我的这个程序中用到了PDO对象, 连接mysql 5.  在PHP的默认设置中,只打开了ph ...

随机推荐

  1. history.go(-1)和History.back()的区别

    简单的说就是:go(-1): 返回上一页,原页面表单中的内容会丢失:back(-1): 返回上一页,原页表表单中的内容会保留,一般还是back(-1)用的多

  2. 吐槽下mac的打印机设置

    只有第一次使用的时候,会提示密码和用户名验证,但是如果中途修改了密码, 找了半天都找不到,给人一种挫败感. 最后是在:点击作业队列某一作业右边的刷新按钮,才会弹出验证的对话框, 可能,mac当初设计这 ...

  3. Js实现Table动态添加一行的小例子

    <form id="form1" runat="server"> <div> <table id=" style=&qu ...

  4. DENIED Redis is running in protected mode

    1.开源软件往往做的非常出色,错误的时候,会告诉你原因,以及怎么修改,仔细阅读就能明白.比如这个错误: [root@localhost src]# ./redis-cli -h 172.16.2.16 ...

  5. gitlab配置通过smtp发送邮件(QQ exmail腾讯企业为例)

    gitlab配置通过smtp发送邮件(QQ exmail腾讯企业为例) 首先祭出官网文档链接:https://docs.gitlab.com/omnibus/settings/smtp.html 其实 ...

  6. 【ASP.NET Core】从向 Web API 提交纯文本内容谈起

    前些时日,老周在升级“华南闲肾回收登记平台”时,为了扩展业务,尤其是允许其他开发人员在其他平台向本系统提交有关肾的介绍资料,于是就为该系统增加了几个 Web API. 其中,有关肾的介绍采用纯文本方式 ...

  7. github远程建了分支,本地看不到的问题

    原因:Git  branch -a 查看的是本地仓库的所有分支  远程新建的没有同步前 就是看不到 解决:$git checkout master   //首先切到master分支 $git pull ...

  8. 批处理文件 bat 后台运行

    当运行 批处理文件bat 时 , 会有一个黑窗口显示 , 对于不懂的人来说, 还是很吓人的;  有两种办法,可以让bat后台运行,不出现黑窗口   第一种解决办法(推荐) : 在你写的批处理文件,开头 ...

  9. MySQL技术内幕读书笔记(五)——索引与算法

    索引与算法 INNODB存储引擎索引概述 ​ INNODB存储引擎支持以下几种常见的索引: B+树索引 全文索引 哈希索引 ​ InnoDB存储引擎支持的哈希索引是自适应的.会根据表的情况自动添加 ​ ...

  10. Deep Dive into Spark SQL’s Catalyst Optimizer(中英双语)

    文章标题 Deep Dive into Spark SQL’s Catalyst Optimizer 作者介绍 Michael Armbrust, Yin Huai, Cheng Liang, Rey ...