Skip to content

Commit

Permalink
增加支持open_gauss
Browse files Browse the repository at this point in the history
  • Loading branch information
hbh112233abc committed Dec 24, 2024
1 parent d19ba55 commit 4832ffe
Show file tree
Hide file tree
Showing 6 changed files with 768 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# think-orm driver for DM(达梦),GBase8s(南大通用),KingDatabase(金仓)
# think-orm driver for DM(达梦),GBase8s(南大通用),OpenGauss(高斯)

## 安装

Expand Down
113 changes: 113 additions & 0 deletions src/builder/OpenGauss.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php
declare(strict_types=1);

namespace bingher\db\builder;

use think\db\Builder;
use think\db\BaseQuery as Query;
use think\db\Raw;

/**
* OpenGauss数据库驱动.
*/
class OpenGauss extends Builder
{
/**
* INSERT SQL表达式.
*
* @var string
*/
protected $insertSql = 'INSERT INTO %TABLE% (%FIELD%) VALUES (%DATA%) %COMMENT%';

/**
* INSERT ALL SQL表达式.
*
* @var string
*/
protected $insertAllSql = 'INSERT INTO %TABLE% (%FIELD%) %DATA% %COMMENT%';

/**
* limit分析.
*
* @param Query $query 查询对象
* @param mixed $limit
*
* @return string
*/
public function parseLimit(Query $query, string $limit): string
{
$limitStr = '';

if (!empty($limit)) {
$limit = explode(',', $limit);
if (count($limit) > 1) {
$limitStr .= ' LIMIT ' . $limit[1] . ' OFFSET ' . $limit[0] . ' ';
} else {
$limitStr .= ' LIMIT ' . $limit[0] . ' ';
}
}

return $limitStr;
}

/**
* 字段和表名处理.
*
* @param Query $query 查询对象
* @param string|int|Raw $key 字段名
* @param bool $strict 严格检测
*
* @return string
*/
public function parseKey(Query $query, string|int|Raw $key, bool $strict = false): string
{
if (is_int($key)) {
return (string) $key;
} elseif ($key instanceof Raw) {
return $this->parseRaw($query, $key);
}

$key = trim($key);

if (str_contains($key, '->') && !str_contains($key, '(')) {
// JSON字段支持
[$field, $name] = explode('->', $key);
$key = '"' . $field . '"' . '->>\'' . $name . '\'';
} elseif (str_contains($key, '.')) {
[$table, $key] = explode('.', $key, 2);

$alias = $query->getOptions('alias');

if ('__TABLE__' == $table) {
$table = $query->getOptions('table');
$table = is_array($table) ? array_shift($table) : $table;
}

if (isset($alias[$table])) {
$table = $alias[$table];
}

if ('*' != $key && !preg_match('/[,\"\*\(\).\s]/', $key)) {
$key = '"' . $key . '"';
}
}

if (isset($table)) {
$key = $table . '.' . $key;
}

return $key;
}

/**
* 随机排序.
*
* @param Query $query 查询对象
*
* @return string
*/
protected function parseRand(Query $query): string
{
return 'RANDOM()';
}
}
162 changes: 162 additions & 0 deletions src/connector/OpenGauss.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
<?php
declare(strict_types=1);

namespace bingher\db\connector;

use PDO;
use think\db\PDOConnection;

/**
* OpenGauss数据库驱动.
*/
class OpenGauss extends PDOConnection
{

/**
* 默认PDO连接参数.
*
* @var array
*/
protected $params = [
PDO::ATTR_CASE => PDO::CASE_NATURAL,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
PDO::ATTR_STRINGIFY_FETCHES => false,
];

/**
* 数据库归属用户
* @var string
*/
protected $owner = '';

function __construct(array $config)
{
parent::__construct($config);
$this->owner = $config['username'];
}

static function pgType(string $type): string
{
switch ($type) {
case 'int8':
$type = 'bigint';
break;
case 'int4':
$type = 'integer';
break;
case 'int2':
$type = 'smallint';
break;
case 'bpchar':
$type = 'char';
break;
}
return $type;
}

/**
* 解析pdo连接的dsn信息.
*
* @param array $config 连接信息
*
* @return string
*/
protected function parseDsn(array $config): string
{
$dsn = 'pgsql:dbname=' . $config['database'] . ';host=' . $config['hostname'];

if (!empty($config['hostport'])) {
$dsn .= ';port=' . $config['hostport'];
}

return $dsn;
}

/**
* 取得数据表的字段信息.
*
* @param string $tableName
*
* @return array
*/
public function getFields(string $tableName): array
{
[$tableName] = explode(' ', $tableName);

$sql = <<<EOF
SELECT
a.attnum,
a.attname AS field,
e.typname AS type,
a.attnotnull AS null,
pg_get_expr(b.adbin, b.adrelid) AS default,
c.description AS column_comment,
d.contype AS key
FROM
pg_catalog.pg_attribute a
LEFT JOIN
pg_catalog.pg_attrdef b ON a.attrelid = b.adrelid AND a.attnum = b.adnum
LEFT JOIN
pg_catalog.pg_description c ON c.objoid = a.attrelid AND c.objsubid = a.attnum
LEFT JOIN
pg_catalog.pg_constraint d ON a.attrelid = d.conrelid AND a.attnum = ANY(d.conkey)
LEFT JOIN pg_type e ON a.atttypid = e.oid
WHERE
a.attrelid = '$tableName'::regclass -- 替换为你的表名
AND a.attnum > 0
AND NOT a.attisdropped
ORDER BY
a.attnum;
EOF;

$logSql = $this->config['trigger_sql'];
$this->config['trigger_sql'] = false;

$pdo = $this->getPDOStatement($sql);
$result = $pdo->fetchAll(PDO::FETCH_ASSOC);

$this->config['trigger_sql'] = $logSql;
$info = [];

if (!empty($result)) {
foreach ($result as $key => $val) {
$val = array_change_key_case($val);

$info[$val['field']] = [
'name' => $val['field'],
'type' => static::pgType($val['type']),
'notnull' => (bool) $val['null'],
'default' => $val['default'],
'primary' => $val['key'] == 'p',
'autoinc' => str_starts_with((string) $val['default'], 'nextval('),
];
}
}

return $this->fieldCase($info);
}

/**
* 取得数据库的表信息.
*
* @param string $dbName
*
* @return array
*/
public function getTables(string $dbName = ''): array
{
$sql = sprintf(
"SELECT tablename AS Tables_in_test FROM pg_tables WHERE tableowner ='%s'",
$this->owner,
);
$pdo = $this->getPDOStatement($sql);
$result = $pdo->fetchAll(PDO::FETCH_COLUMN);
return $result;
}

protected function supportSavepoint(): bool
{
return true;
}
}
8 changes: 8 additions & 0 deletions src/query/OpenGauss.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php
namespace bingher\db\query;

use think\db\Query;

class OpenGauss extends Query
{
}
Loading

0 comments on commit 4832ffe

Please sign in to comment.