2020-03-02 16:14:20 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace ZM\DB;
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-05-10 14:11:32 +08:00
|
|
|
|
use Exception;
|
2020-03-02 16:14:20 +08:00
|
|
|
|
use framework\Console;
|
|
|
|
|
|
use framework\ZMBuf;
|
2020-05-10 14:11:32 +08:00
|
|
|
|
use PDOStatement;
|
2020-03-02 16:14:20 +08:00
|
|
|
|
use Swoole\Coroutine;
|
2020-05-23 17:23:29 +08:00
|
|
|
|
use Swoole\Database\PDOStatementProxy;
|
2020-03-02 16:14:20 +08:00
|
|
|
|
use ZM\Exception\DbException;
|
|
|
|
|
|
|
|
|
|
|
|
class DB
|
|
|
|
|
|
{
|
|
|
|
|
|
private static $table_list = [];
|
|
|
|
|
|
|
2020-04-29 15:29:56 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @throws DbException
|
2020-05-10 14:11:32 +08:00
|
|
|
|
* @throws Exception
|
2020-04-29 15:29:56 +08:00
|
|
|
|
*/
|
2020-03-02 16:14:20 +08:00
|
|
|
|
public static function initTableList() {
|
2020-05-10 14:11:32 +08:00
|
|
|
|
if (!extension_loaded("mysqlnd")) throw new Exception("Can not find mysqlnd PHP extension.");
|
2020-03-02 16:14:20 +08:00
|
|
|
|
$result = self::rawQuery("select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='" . ZMBuf::globals("sql_config")["sql_database"] . "';", []);
|
|
|
|
|
|
foreach ($result as $v) {
|
|
|
|
|
|
self::$table_list[] = $v['TABLE_NAME'];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @param $table_name
|
|
|
|
|
|
* @param bool $enable_cache
|
|
|
|
|
|
* @return Table
|
|
|
|
|
|
* @throws DbException
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function table($table_name, $enable_cache = null) {
|
|
|
|
|
|
if (Table::getTableInstance($table_name) === null) {
|
|
|
|
|
|
if (in_array($table_name, self::$table_list))
|
|
|
|
|
|
return new Table($table_name, $enable_cache ?? ZMBuf::globals("sql_config")["sql_enable_cache"]);
|
|
|
|
|
|
elseif(ZMBuf::$sql_pool !== null){
|
|
|
|
|
|
throw new DbException("Table " . $table_name . " not exist in database.");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
throw new DbException("Database connection not exist or connect failed. Please check sql configuration");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return Table::getTableInstance($table_name);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-04-29 15:29:56 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @param $line
|
|
|
|
|
|
* @throws DbException
|
|
|
|
|
|
*/
|
2020-03-02 16:14:20 +08:00
|
|
|
|
public static function statement($line) {
|
|
|
|
|
|
self::rawQuery($line, []);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-04-29 15:29:56 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @param $line
|
|
|
|
|
|
* @return bool
|
|
|
|
|
|
* @throws DbException
|
|
|
|
|
|
*/
|
2020-03-02 16:14:20 +08:00
|
|
|
|
public static function unprepared($line) {
|
|
|
|
|
|
if (ZMBuf::get("sql_log") === true) {
|
|
|
|
|
|
$starttime = microtime(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
|
|
|
$conn = ZMBuf::$sql_pool->get();
|
|
|
|
|
|
if ($conn === false) {
|
2020-05-23 17:23:29 +08:00
|
|
|
|
ZMBuf::$sql_pool->put(null);
|
2020-03-02 16:14:20 +08:00
|
|
|
|
throw new DbException("无法连接SQL!" . $line);
|
|
|
|
|
|
}
|
2020-05-23 17:23:29 +08:00
|
|
|
|
$result = $conn->query($line) === false ? false : true;
|
2020-03-02 16:14:20 +08:00
|
|
|
|
ZMBuf::$sql_pool->put($conn);
|
|
|
|
|
|
return $result;
|
|
|
|
|
|
} catch (DBException $e) {
|
|
|
|
|
|
if (ZMBuf::get("sql_log") === true) {
|
|
|
|
|
|
$log =
|
|
|
|
|
|
"[" . date("Y-m-d H:i:s") .
|
|
|
|
|
|
" " . round(microtime(true) - $starttime, 5) .
|
|
|
|
|
|
"] " . $line . " (Error:" . $e->getMessage() . ")\n";
|
|
|
|
|
|
Coroutine::writeFile(CRASH_DIR . "sql.log", $log, FILE_APPEND);
|
|
|
|
|
|
}
|
2020-04-29 15:29:56 +08:00
|
|
|
|
Console::warning($e->getMessage());
|
|
|
|
|
|
throw $e;
|
2020-03-02 16:14:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-04-29 15:29:56 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @param string $line
|
|
|
|
|
|
* @param array $params
|
|
|
|
|
|
* @return mixed
|
|
|
|
|
|
* @throws DbException
|
|
|
|
|
|
*/
|
2020-04-26 15:01:18 +08:00
|
|
|
|
public static function rawQuery(string $line, $params = []) {
|
2020-03-02 16:14:20 +08:00
|
|
|
|
if (ZMBuf::get("sql_log") === true) {
|
|
|
|
|
|
$starttime = microtime(true);
|
|
|
|
|
|
}
|
2020-05-02 23:27:26 +08:00
|
|
|
|
Console::debug("MySQL: ".$line);
|
2020-03-02 16:14:20 +08:00
|
|
|
|
try {
|
|
|
|
|
|
$conn = ZMBuf::$sql_pool->get();
|
|
|
|
|
|
if ($conn === false) {
|
2020-05-23 17:23:29 +08:00
|
|
|
|
ZMBuf::$sql_pool->put(null);
|
2020-03-02 16:14:20 +08:00
|
|
|
|
throw new DbException("无法连接SQL!" . $line);
|
|
|
|
|
|
}
|
|
|
|
|
|
$ps = $conn->prepare($line);
|
|
|
|
|
|
if ($ps === false) {
|
2020-05-23 17:23:29 +08:00
|
|
|
|
ZMBuf::$sql_pool->put(null);
|
2020-03-02 16:14:20 +08:00
|
|
|
|
throw new DbException("SQL语句查询错误," . $line . ",错误信息:" . $conn->error);
|
|
|
|
|
|
} else {
|
2020-05-23 17:23:29 +08:00
|
|
|
|
if (!($ps instanceof PDOStatement) && !($ps instanceof PDOStatementProxy)) {
|
|
|
|
|
|
var_dump($ps);
|
|
|
|
|
|
ZMBuf::$sql_pool->put(null);
|
|
|
|
|
|
throw new DbException("语句查询错误!返回的不是 PDOStatement" . $line);
|
2020-03-02 16:14:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
if ($params == []) $result = $ps->execute();
|
|
|
|
|
|
elseif (!is_array($params)) {
|
|
|
|
|
|
$result = $ps->execute([$params]);
|
|
|
|
|
|
} else $result = $ps->execute($params);
|
2020-05-10 14:11:32 +08:00
|
|
|
|
if ($result !== true) {
|
2020-05-23 17:23:29 +08:00
|
|
|
|
ZMBuf::$sql_pool->put(null);
|
2020-05-10 14:11:32 +08:00
|
|
|
|
throw new DBException("语句[$line]错误!" . $ps->errorInfo()[2]);
|
2020-03-02 16:14:20 +08:00
|
|
|
|
//echo json_encode(debug_backtrace(), 128 | 256);
|
|
|
|
|
|
}
|
2020-05-23 17:23:29 +08:00
|
|
|
|
ZMBuf::$sql_pool->put($conn);
|
2020-03-02 16:14:20 +08:00
|
|
|
|
if (ZMBuf::get("sql_log") === true) {
|
|
|
|
|
|
$log =
|
|
|
|
|
|
"[" . date("Y-m-d H:i:s") .
|
|
|
|
|
|
" " . round(microtime(true) - $starttime, 4) .
|
|
|
|
|
|
"] " . $line . " " . json_encode($params, JSON_UNESCAPED_UNICODE) . "\n";
|
|
|
|
|
|
Coroutine::writeFile(CRASH_DIR . "sql.log", $log, FILE_APPEND);
|
|
|
|
|
|
}
|
2020-05-10 14:11:32 +08:00
|
|
|
|
return $ps->fetchAll();
|
2020-03-02 16:14:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
} catch (DBException $e) {
|
|
|
|
|
|
if (ZMBuf::get("sql_log") === true) {
|
|
|
|
|
|
$log =
|
|
|
|
|
|
"[" . date("Y-m-d H:i:s") .
|
|
|
|
|
|
" " . round(microtime(true) - $starttime, 4) .
|
|
|
|
|
|
"] " . $line . " " . json_encode($params, JSON_UNESCAPED_UNICODE) . " (Error:" . $e->getMessage() . ")\n";
|
|
|
|
|
|
Coroutine::writeFile(CRASH_DIR . "sql.log", $log, FILE_APPEND);
|
|
|
|
|
|
}
|
2020-05-23 17:23:29 +08:00
|
|
|
|
if(mb_strpos($e->getMessage(), "has gone away") !== false) {
|
|
|
|
|
|
zm_sleep(0.2);
|
|
|
|
|
|
Console::warning("Gone away of MySQL! retrying!");
|
|
|
|
|
|
return self::rawQuery($line, $params);
|
|
|
|
|
|
}
|
2020-04-29 15:29:56 +08:00
|
|
|
|
Console::warning($e->getMessage());
|
|
|
|
|
|
throw $e;
|
2020-03-02 16:14:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-04-26 15:01:18 +08:00
|
|
|
|
|
|
|
|
|
|
public static function isTableExists($table) {
|
|
|
|
|
|
return in_array($table, self::$table_list);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|