mirror of
https://github.com/typecho/typecho.git
synced 2025-01-17 20:48:42 +01:00
fix pgsql
This commit is contained in:
parent
75672fe259
commit
c422952c89
18
install.php
18
install.php
@ -20,7 +20,7 @@ if (!file_exists(dirname(__FILE__) . '/config.inc.php')) {
|
||||
\Typecho\Common::init();
|
||||
} else {
|
||||
require_once dirname(__FILE__) . '/config.inc.php';
|
||||
$installDb = Typecho_Db::get();
|
||||
$installDb = \Typecho\Db::get();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -259,9 +259,9 @@ require_once __TYPECHO_ROOT_DIR__ . '/var/Typecho/Common.php';
|
||||
\Typecho\Common::init();
|
||||
|
||||
// config db
|
||||
\$db = new Typecho_Db('{$adapter}', '{$dbPrefix}');
|
||||
\$db->addServer(" . (var_export($dbConfig, true)) . ", Typecho_Db::READ | Typecho_Db::WRITE);
|
||||
Typecho_Db::set(\$db);
|
||||
\$db = new \Typecho\Db('{$adapter}', '{$dbPrefix}');
|
||||
\$db->addServer(" . (var_export($dbConfig, true)) . ", \Typecho\Db::READ | \Typecho\Db::WRITE);
|
||||
\Typecho\Db::set(\$db);
|
||||
";
|
||||
|
||||
$configWritten = false;
|
||||
@ -551,7 +551,7 @@ function install_step_2()
|
||||
$type = install_get_db_type($adapter);
|
||||
|
||||
if (!empty($installDb)) {
|
||||
$config = $installDb->getConfig(Typecho_Db::WRITE)->toArray();
|
||||
$config = $installDb->getConfig(\Typecho\Db::WRITE)->toArray();
|
||||
$config['prefix'] = $installDb->getPrefix();
|
||||
$config['adapter'] = $adapter;
|
||||
}
|
||||
@ -748,7 +748,7 @@ function install_step_2_perform()
|
||||
$dbConfig = [];
|
||||
|
||||
foreach ($configMap[$type] as $key => $value) {
|
||||
$config[$key] = $config[$key] === null ? (install_is_cli() ? $value : null) : $config[$key];
|
||||
$config[$key] = !isset($config[$key]) ? (install_is_cli() ? $value : null) : $config[$key];
|
||||
}
|
||||
|
||||
switch ($type) {
|
||||
@ -801,8 +801,8 @@ function install_step_2_perform()
|
||||
} elseif (empty($installDb)) {
|
||||
// detect db config
|
||||
try {
|
||||
$installDb = new Typecho_Db($config['dbAdapter'], $config['dbPrefix']);
|
||||
$installDb->addServer($dbConfig, Typecho_Db::READ | Typecho_Db::WRITE);
|
||||
$installDb = new \Typecho\Db($config['dbAdapter'], $config['dbPrefix']);
|
||||
$installDb->addServer($dbConfig, \Typecho\Db::READ | \Typecho\Db::WRITE);
|
||||
$installDb->query('SELECT 1=1');
|
||||
} catch (\Typecho\Db\Adapter_Exception $e) {
|
||||
install_raise_error(_t('对不起, 无法连接数据库, 请先检查数据库配置再继续进行安装'));
|
||||
@ -867,7 +867,7 @@ function install_step_2_perform()
|
||||
foreach ($scripts as $script) {
|
||||
$script = trim($script);
|
||||
if ($script) {
|
||||
$installDb->query($script, Typecho_Db::WRITE);
|
||||
$installDb->query($script, \Typecho\Db::WRITE);
|
||||
}
|
||||
}
|
||||
} catch (\Typecho\Db\Exception $e) {
|
||||
|
@ -812,7 +812,7 @@ EOF;
|
||||
*/
|
||||
public static function hashValidate(?string $from, ?string $to): bool
|
||||
{
|
||||
if ($from === null || $to === null) {
|
||||
if (!isset($from) || !isset($to)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -836,7 +836,7 @@ EOF;
|
||||
*/
|
||||
public static function hash(?string $string, ?string $salt = null): string
|
||||
{
|
||||
if ($string === null) {
|
||||
if (!isset($string)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
@ -929,19 +929,19 @@ EOF;
|
||||
/**
|
||||
* 获取gravatar头像地址
|
||||
*
|
||||
* @param string $mail
|
||||
* @param string|null $mail
|
||||
* @param int $size
|
||||
* @param string $rating
|
||||
* @param string $default
|
||||
* @param string|null $rating
|
||||
* @param string|null $default
|
||||
* @param bool $isSecure
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function gravatarUrl(
|
||||
string $mail,
|
||||
?string $mail,
|
||||
int $size,
|
||||
string $rating,
|
||||
string $default,
|
||||
?string $rating = null,
|
||||
?string $default = null,
|
||||
bool $isSecure = true
|
||||
): string {
|
||||
if (defined('__TYPECHO_GRAVATAR_PREFIX__')) {
|
||||
@ -956,8 +956,14 @@ EOF;
|
||||
}
|
||||
|
||||
$url .= '?s=' . $size;
|
||||
$url .= '&r=' . $rating;
|
||||
$url .= '&d=' . $default;
|
||||
|
||||
if (isset($rating)) {
|
||||
$url .= '&r=' . $rating;
|
||||
}
|
||||
|
||||
if (isset($default)) {
|
||||
$url .= '&d=' . $default;
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ class Db
|
||||
public function __construct($adapterName, string $prefix = 'typecho_')
|
||||
{
|
||||
/** 获取适配器名称 */
|
||||
$this->adapterName = $adapterName;
|
||||
$this->adapterName = $adapterName == 'Mysql' ? 'Mysqli' : $adapterName;
|
||||
|
||||
/** 数据库适配器 */
|
||||
$adapterName = '\Typecho\Db\Adapter\\' . str_replace('_', '\\', $adapterName);
|
||||
|
@ -71,7 +71,7 @@ interface Adapter
|
||||
* @param resource $resource 查询的资源数据
|
||||
* @return array
|
||||
*/
|
||||
public function fetchAll($resource): ?array;
|
||||
public function fetchAll($resource): array;
|
||||
|
||||
/**
|
||||
* 将数据查询的其中一行作为对象取出,其中字段名对应对象属性
|
||||
|
@ -4,6 +4,8 @@ namespace Typecho\Db\Adapter;
|
||||
|
||||
trait MysqlTrait
|
||||
{
|
||||
use QueryTrait;
|
||||
|
||||
/**
|
||||
* 清空数据表
|
||||
*
|
||||
@ -25,17 +27,6 @@ trait MysqlTrait
|
||||
*/
|
||||
public function parseSelect(array $sql): string
|
||||
{
|
||||
if (!empty($sql['join'])) {
|
||||
foreach ($sql['join'] as $val) {
|
||||
[$table, $condition, $op] = $val;
|
||||
$sql['table'] = "{$sql['table']} {$op} JOIN {$table} ON {$condition}";
|
||||
}
|
||||
}
|
||||
|
||||
$sql['limit'] = (0 == strlen($sql['limit'])) ? null : ' LIMIT ' . $sql['limit'];
|
||||
$sql['offset'] = (0 == strlen($sql['offset'])) ? null : ' OFFSET ' . $sql['offset'];
|
||||
|
||||
return 'SELECT ' . $sql['fields'] . ' FROM ' . $sql['table'] .
|
||||
$sql['where'] . $sql['group'] . $sql['having'] . $sql['order'] . $sql['limit'] . $sql['offset'];
|
||||
return $this->buildQuery($sql);
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,11 @@ class Mysql extends Pdo
|
||||
$config->password
|
||||
);
|
||||
$pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
|
||||
$pdo->exec("SET NAMES '{$config->charset}'");
|
||||
|
||||
if ($config->charset) {
|
||||
$pdo->exec("SET NAMES '{$config->charset}'");
|
||||
}
|
||||
|
||||
return $pdo;
|
||||
}
|
||||
|
||||
|
@ -1,33 +1,25 @@
|
||||
<?php
|
||||
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
|
||||
/**
|
||||
* Typecho Blog Platform
|
||||
*
|
||||
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
|
||||
* @license GNU General Public License 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace Typecho\Db\Adapter\Pdo;
|
||||
|
||||
use Typecho\Config;
|
||||
use Typecho\Db;
|
||||
use Typecho\Db\Adapter\Exception;
|
||||
use Typecho\Db\Adapter\Pdo;
|
||||
use Typecho\Db\Adapter\PgsqlTrait;
|
||||
|
||||
if (!defined('__TYPECHO_ROOT_DIR__')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据库Pdo_Pgsql适配器
|
||||
*
|
||||
* @package Db
|
||||
*/
|
||||
class Typecho_Db_Adapter_Pdo_Pgsql extends Typecho_Db_Adapter_Pdo
|
||||
class Pgsql extends Pdo
|
||||
{
|
||||
/**
|
||||
* 主键列表
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $_pk = [];
|
||||
|
||||
/**
|
||||
* 兼容的插入模式
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $_compatibleInsert = false;
|
||||
use PgsqlTrait;
|
||||
|
||||
/**
|
||||
* 判断适配器是否可用
|
||||
@ -35,134 +27,51 @@ class Typecho_Db_Adapter_Pdo_Pgsql extends Typecho_Db_Adapter_Pdo
|
||||
* @access public
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isAvailable()
|
||||
public static function isAvailable(): bool
|
||||
{
|
||||
return parent::isAvailable() && in_array('pgsql', PDO::getAvailableDrivers());
|
||||
return parent::isAvailable() && in_array('pgsql', \PDO::getAvailableDrivers());
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空数据表
|
||||
* 执行数据库查询
|
||||
*
|
||||
* @param string $table
|
||||
* @param mixed $handle 连接对象
|
||||
* @return mixed|void
|
||||
* @throws Typecho_Db_Exception
|
||||
* @param string $query 数据库查询SQL字符串
|
||||
* @param \PDO $handle 连接对象
|
||||
* @param integer $op 数据库读写状态
|
||||
* @param string|null $action 数据库动作
|
||||
* @param string|null $table 数据表
|
||||
* @return \PDOStatement
|
||||
* @throws Exception
|
||||
*/
|
||||
public function truncate($table, $handle)
|
||||
{
|
||||
$this->query('TRUNCATE TABLE ' . $this->quoteColumn($table) . ' RESTART IDENTITY', $handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* 覆盖标准动作
|
||||
* fix #710
|
||||
*
|
||||
* @param string $query
|
||||
* @param mixed $handle
|
||||
* @param int $op
|
||||
* @param null $action
|
||||
* @param null $table
|
||||
* @return resource
|
||||
* @throws Typecho_Db_Exception
|
||||
*/
|
||||
public function query($query, $handle, $op = Typecho_Db::READ, $action = null, $table = null)
|
||||
{
|
||||
if (Typecho_Db::INSERT == $action && !empty($table)) {
|
||||
if (!isset($this->_pk[$table])) {
|
||||
$result = $handle->query("SELECT
|
||||
pg_attribute.attname,
|
||||
format_type(pg_attribute.atttypid, pg_attribute.atttypmod)
|
||||
FROM pg_index, pg_class, pg_attribute, pg_namespace
|
||||
WHERE
|
||||
pg_class.oid = " . $this->quoteValue($table) . "::regclass AND
|
||||
indrelid = pg_class.oid AND
|
||||
nspname = 'public' AND
|
||||
pg_class.relnamespace = pg_namespace.oid AND
|
||||
pg_attribute.attrelid = pg_class.oid AND
|
||||
pg_attribute.attnum = any(pg_index.indkey)
|
||||
AND indisprimary")->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!empty($result)) {
|
||||
$this->_pk[$table] = $result['attname'];
|
||||
}
|
||||
}
|
||||
|
||||
// 使用兼容模式监听插入结果
|
||||
if (isset($this->_pk[$table])) {
|
||||
$this->_compatibleInsert = true;
|
||||
$query .= ' RETURNING ' . $this->quoteColumn($this->_pk[$table]);
|
||||
}
|
||||
}
|
||||
|
||||
return parent::query($query, $handle, $op, $action, $table); // TODO: Change the autogenerated stub
|
||||
}
|
||||
|
||||
/**
|
||||
* 对象引号过滤
|
||||
*
|
||||
* @access public
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
public function quoteColumn($string)
|
||||
{
|
||||
return '"' . $string . '"';
|
||||
public function query(
|
||||
string $query,
|
||||
$handle,
|
||||
int $op = Db::READ,
|
||||
?string $action = null,
|
||||
?string $table = null
|
||||
): \PDOStatement {
|
||||
$this->prepareQuery($query, $handle, $action, $table);
|
||||
return parent::query($query, $handle, $op, $action, $table);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化数据库
|
||||
*
|
||||
* @param Typecho_Config $config 数据库配置
|
||||
* @access public
|
||||
* @return PDO
|
||||
* @param Config $config 数据库配置
|
||||
* @return \PDO
|
||||
*/
|
||||
public function init(Typecho_Config $config)
|
||||
public function init(Config $config): \PDO
|
||||
{
|
||||
$pdo = new PDO("pgsql:dbname={$config->database};host={$config->host};port={$config->port}", $config->user, $config->password);
|
||||
$pdo->exec("SET NAMES '{$config->charset}'");
|
||||
$pdo = new \PDO(
|
||||
"pgsql:dbname={$config->database};host={$config->host};port={$config->port}",
|
||||
$config->user,
|
||||
$config->password
|
||||
);
|
||||
|
||||
if ($config->charset) {
|
||||
$pdo->exec("SET NAMES '{$config->charset}'");
|
||||
}
|
||||
|
||||
return $pdo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 合成查询语句
|
||||
*
|
||||
* @access public
|
||||
* @param array $sql 查询对象词法数组
|
||||
* @return string
|
||||
*/
|
||||
public function parseSelect(array $sql)
|
||||
{
|
||||
if (!empty($sql['join'])) {
|
||||
foreach ($sql['join'] as $val) {
|
||||
[$table, $condition, $op] = $val;
|
||||
$sql['table'] = "{$sql['table']} {$op} JOIN {$table} ON {$condition}";
|
||||
}
|
||||
}
|
||||
|
||||
$sql['limit'] = (0 == strlen($sql['limit'])) ? null : ' LIMIT ' . $sql['limit'];
|
||||
$sql['offset'] = (0 == strlen($sql['offset'])) ? null : ' OFFSET ' . $sql['offset'];
|
||||
|
||||
return 'SELECT ' . $sql['fields'] . ' FROM ' . $sql['table'] .
|
||||
$sql['where'] . $sql['group'] . $sql['having'] . $sql['order'] . $sql['limit'] . $sql['offset'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 取出最后一次插入返回的主键值
|
||||
*
|
||||
* @param resource $resource 查询的资源数据
|
||||
* @param mixed $handle 连接对象
|
||||
* @return integer
|
||||
*/
|
||||
public function lastInsertId($resource, $handle)
|
||||
{
|
||||
if ($this->_compatibleInsert) {
|
||||
$this->_compatibleInsert = false;
|
||||
return $resource->fetchColumn(0);
|
||||
} elseif ($handle->query('SELECT oid FROM pg_class WHERE relname = ' . $this->quoteValue($this->_lastTable . '_seq'))->fetchAll()) {
|
||||
/** 查看是否存在序列,可能需要更严格的检查 */
|
||||
return $handle->lastInsertId($this->_lastTable . '_seq');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -17,21 +17,7 @@ if (!defined('__TYPECHO_ROOT_DIR__')) {
|
||||
*/
|
||||
class Pgsql implements Adapter
|
||||
{
|
||||
/**
|
||||
* 最后一次操作的数据表
|
||||
*
|
||||
* @access protected
|
||||
* @var string
|
||||
*/
|
||||
protected $_lastTable;
|
||||
|
||||
/**
|
||||
* 数据库连接字符串标示
|
||||
*
|
||||
* @access private
|
||||
* @var resource
|
||||
*/
|
||||
private $_dbLink;
|
||||
use PgsqlTrait;
|
||||
|
||||
/**
|
||||
* 判断适配器是否可用
|
||||
@ -54,17 +40,17 @@ class Pgsql implements Adapter
|
||||
public function connect(Config $config)
|
||||
{
|
||||
if (
|
||||
$this->_dbLink = pg_connect("host={$config->host} port={$config->port}"
|
||||
$dbLink = pg_connect("host={$config->host} port={$config->port}"
|
||||
. " dbname={$config->database} user={$config->user} password={$config->password}")
|
||||
) {
|
||||
if ($config->charset) {
|
||||
pg_query($this->_dbLink, "SET NAMES '{$config->charset}'");
|
||||
pg_query($dbLink, "SET NAMES '{$config->charset}'");
|
||||
}
|
||||
return $this->_dbLink;
|
||||
return $dbLink;
|
||||
}
|
||||
|
||||
/** 数据库异常 */
|
||||
throw new Exception(pg_last_error($this->_dbLink));
|
||||
throw new Exception(pg_last_error($dbLink));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,18 +65,6 @@ class Pgsql implements Adapter
|
||||
return 'pgsql:pgsql ' . $version['server'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空数据表
|
||||
*
|
||||
* @param string $table
|
||||
* @param resource $handle 连接对象
|
||||
* @throws Exception
|
||||
*/
|
||||
public function truncate(string $table, $handle)
|
||||
{
|
||||
$this->query('TRUNCATE TABLE ' . $this->quoteColumn($table) . ' RESTART IDENTITY', $handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行数据库查询
|
||||
*
|
||||
@ -104,7 +78,7 @@ class Pgsql implements Adapter
|
||||
*/
|
||||
public function query(string $query, $handle, int $op = Db::READ, ?string $action = null, ?string $table = null)
|
||||
{
|
||||
$this->_lastTable = $table;
|
||||
$this->prepareQuery($query, $handle, $action, $table);
|
||||
if ($resource = pg_query($handle, $query)) {
|
||||
return $resource;
|
||||
}
|
||||
@ -138,6 +112,15 @@ class Pgsql implements Adapter
|
||||
return pg_fetch_object($resource) ?: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource $resource
|
||||
* @return array|null
|
||||
*/
|
||||
public function fetchAll($resource): array
|
||||
{
|
||||
return pg_fetch_all($resource, PGSQL_ASSOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取出最后一次查询影响的行数
|
||||
*
|
||||
@ -150,23 +133,6 @@ class Pgsql implements Adapter
|
||||
return pg_affected_rows($resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取出最后一次插入返回的主键值
|
||||
*
|
||||
* @param resource $resource 查询的资源数据
|
||||
* @param resource $handle 连接对象
|
||||
* @return integer
|
||||
*/
|
||||
public function lastInsertId($resource, $handle)
|
||||
{
|
||||
/** 查看是否存在序列,可能需要更严格的检查 */
|
||||
if (pg_fetch_assoc(pg_query($handle, 'SELECT oid FROM pg_class WHERE relname = ' . $this->quoteValue($this->_lastTable . '_seq')))) {
|
||||
return pg_fetch_result(pg_query($handle, 'SELECT CURRVAL(' . $this->quoteValue($this->_lastTable . '_seq') . ')'), 0, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 引号转义函数
|
||||
*
|
||||
|
@ -2,8 +2,39 @@
|
||||
|
||||
namespace Typecho\Db\Adapter;
|
||||
|
||||
use Typecho\Db;
|
||||
|
||||
trait PgsqlTrait
|
||||
{
|
||||
use QueryTrait;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $pk = [];
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $compatibleInsert = false;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $lastTable = null;
|
||||
|
||||
/**
|
||||
* 清空数据表
|
||||
*
|
||||
* @param string $table
|
||||
* @param resource $handle 连接对象
|
||||
* @throws Exception
|
||||
*/
|
||||
public function truncate(string $table, $handle)
|
||||
{
|
||||
$this->query('TRUNCATE TABLE ' . $this->quoteColumn($table) . ' RESTART IDENTITY', $handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* 合成查询语句
|
||||
*
|
||||
@ -13,18 +44,7 @@ trait PgsqlTrait
|
||||
*/
|
||||
public function parseSelect(array $sql): string
|
||||
{
|
||||
if (!empty($sql['join'])) {
|
||||
foreach ($sql['join'] as $val) {
|
||||
[$table, $condition, $op] = $val;
|
||||
$sql['table'] = "{$sql['table']} {$op} JOIN {$table} ON {$condition}";
|
||||
}
|
||||
}
|
||||
|
||||
$sql['limit'] = (0 == strlen($sql['limit'])) ? null : ' LIMIT ' . $sql['limit'];
|
||||
$sql['offset'] = (0 == strlen($sql['offset'])) ? null : ' OFFSET ' . $sql['offset'];
|
||||
|
||||
return 'SELECT ' . $sql['fields'] . ' FROM ' . $sql['table'] .
|
||||
$sql['where'] . $sql['group'] . $sql['having'] . $sql['order'] . $sql['limit'] . $sql['offset'];
|
||||
return $this->buildQuery($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,4 +58,110 @@ trait PgsqlTrait
|
||||
{
|
||||
return '"' . $string . '"';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $query
|
||||
* @param $handle
|
||||
* @param string|null $action
|
||||
* @param string|null $table
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function prepareQuery(string &$query, $handle, ?string $action = null, ?string $table = null)
|
||||
{
|
||||
if (Db::INSERT == $action && !empty($table)) {
|
||||
$this->compatibleInsert = false;
|
||||
$this->lastTable = $table;
|
||||
|
||||
if (!isset($this->pk[$table])) {
|
||||
$resource = $this->query("SELECT
|
||||
pg_attribute.attname,
|
||||
format_type(pg_attribute.atttypid, pg_attribute.atttypmod)
|
||||
FROM pg_index, pg_class, pg_attribute, pg_namespace
|
||||
WHERE
|
||||
pg_class.oid = " . $this->quoteValue($table) . "::regclass AND
|
||||
indrelid = pg_class.oid AND
|
||||
nspname = 'public' AND
|
||||
pg_class.relnamespace = pg_namespace.oid AND
|
||||
pg_attribute.attrelid = pg_class.oid AND
|
||||
pg_attribute.attnum = any(pg_index.indkey)
|
||||
AND indisprimary", $handle, Db::READ, Db::SELECT, $table);
|
||||
|
||||
$result = $this->fetch($resource);
|
||||
|
||||
if (!empty($result)) {
|
||||
$this->pk[$table] = $result['attname'];
|
||||
}
|
||||
}
|
||||
|
||||
// 使用兼容模式监听插入结果
|
||||
if (isset($this->pk[$table])) {
|
||||
$this->compatibleInsert = true;
|
||||
$query .= ' RETURNING ' . $this->quoteColumn($this->pk[$table]);
|
||||
}
|
||||
} else {
|
||||
$this->lastTable = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 取出最后一次插入返回的主键值
|
||||
*
|
||||
* @param resource $resource 查询的资源数据
|
||||
* @param resource $handle 连接对象
|
||||
* @return integer
|
||||
* @throws Exception
|
||||
*/
|
||||
public function lastInsertId($resource, $handle): int
|
||||
{
|
||||
$lastTable = $this->lastTable;
|
||||
|
||||
if ($this->compatibleInsert) {
|
||||
$result = $this->fetch($resource);
|
||||
$pk = $this->pk[$lastTable];
|
||||
|
||||
if (!empty($result) && isset($result[$pk])) {
|
||||
return (int) $result[$pk];
|
||||
}
|
||||
} else {
|
||||
$resource = $this->query(
|
||||
'SELECT oid FROM pg_class WHERE relname = '
|
||||
. $this->quoteValue($lastTable . '_seq'),
|
||||
$handle,
|
||||
Db::READ,
|
||||
Db::SELECT,
|
||||
$lastTable
|
||||
);
|
||||
|
||||
$result = $this->fetch($resource);
|
||||
|
||||
if (!empty($result)) {
|
||||
$resource = $this->query(
|
||||
'SELECT CURRVAL(' . $this->quoteValue($lastTable . '_seq') . ') AS last_insert_id',
|
||||
$handle,
|
||||
Db::READ,
|
||||
Db::SELECT,
|
||||
$lastTable
|
||||
);
|
||||
|
||||
$result = $this->fetch($resource);
|
||||
if (!empty($result)) {
|
||||
return (int) $result['last_insert_id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
abstract public function query(
|
||||
string $query,
|
||||
$handle,
|
||||
int $op = Db::READ,
|
||||
?string $action = null,
|
||||
?string $table = null
|
||||
);
|
||||
|
||||
abstract public function quoteValue(string $string): string;
|
||||
|
||||
abstract public function fetch($resource): ?array;
|
||||
}
|
29
var/Typecho/Db/Adapter/QueryTrait.php
Normal file
29
var/Typecho/Db/Adapter/QueryTrait.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Typecho\Db\Adapter;
|
||||
|
||||
/**
|
||||
* Build Sql
|
||||
*/
|
||||
trait QueryTrait
|
||||
{
|
||||
/**
|
||||
* @param array $sql
|
||||
* @return string
|
||||
*/
|
||||
private function buildQuery(array $sql): string
|
||||
{
|
||||
if (!empty($sql['join'])) {
|
||||
foreach ($sql['join'] as $val) {
|
||||
[$table, $condition, $op] = $val;
|
||||
$sql['table'] = "{$sql['table']} {$op} JOIN {$table} ON {$condition}";
|
||||
}
|
||||
}
|
||||
|
||||
$sql['limit'] = (0 == strlen($sql['limit'])) ? null : ' LIMIT ' . $sql['limit'];
|
||||
$sql['offset'] = (0 == strlen($sql['offset'])) ? null : ' OFFSET ' . $sql['offset'];
|
||||
|
||||
return 'SELECT ' . $sql['fields'] . ' FROM ' . $sql['table'] .
|
||||
$sql['where'] . $sql['group'] . $sql['having'] . $sql['order'] . $sql['limit'] . $sql['offset'];
|
||||
}
|
||||
}
|
@ -7,6 +7,8 @@ namespace Typecho\Db\Adapter;
|
||||
*/
|
||||
trait SQLiteTrait
|
||||
{
|
||||
use QueryTrait;
|
||||
|
||||
private $isSQLite2 = false;
|
||||
|
||||
/**
|
||||
@ -89,21 +91,10 @@ trait SQLiteTrait
|
||||
*/
|
||||
public function parseSelect(array $sql): string
|
||||
{
|
||||
if (!empty($sql['join'])) {
|
||||
foreach ($sql['join'] as $val) {
|
||||
[$table, $condition, $op] = $val;
|
||||
$sql['table'] = "{$sql['table']} {$op} JOIN {$table} ON {$condition}";
|
||||
}
|
||||
}
|
||||
|
||||
$sql['limit'] = (0 == strlen($sql['limit'])) ? null : ' LIMIT ' . $sql['limit'];
|
||||
$sql['offset'] = (0 == strlen($sql['offset'])) ? null : ' OFFSET ' . $sql['offset'];
|
||||
|
||||
$query = $this->filterCountQuery('SELECT ' . $sql['fields'] . ' FROM ' . $sql['table'] .
|
||||
$sql['where'] . $sql['group'] . $sql['having'] . $sql['order'] . $sql['limit'] . $sql['offset']);
|
||||
$query = $this->filterCountQuery($this->buildQuery($sql));
|
||||
|
||||
if ($this->isSQLite2) {
|
||||
$query = $this->filterSQLite2CountQuery($query);
|
||||
$query = $this->filterCountQuery($query);
|
||||
}
|
||||
|
||||
return $query;
|
||||
|
Loading…
x
Reference in New Issue
Block a user