ThinkPHP6支持金仓数据库(Kingbase)解决无法使用模型查询问题

参考了很多前人的文章,最后只支持Db::query原生查询,不支持thinkphp数据模型方法,这在实际项目中是很难接受的,特分享出解决方案。

先按照流程配置如下:

1.准备工作

首先确认PHP支持金仓数据库的扩展,可以去金仓官网下载,安装配置(详细配置略过......)。

使用 php -m 命令检查,显示有 pdo_kdb即可。 这里注意一下libpq.dll的版本要>=10,否则会报错误。

2,新增金仓数据库的connenter类

进到ThinkPHP项目目录下的vendor\topthink\think-orm\src\db\connector\下,复制Pgsql.php为Kingbase.php(基于pgsql修改),修改文件中的类名为Kingbase。

复制代码
/**
 * Kingbase数据库驱动
 */
class Kingbase extends PDOConnection

找到 protected function parseDsn(array $config): string 方法,修改该方法下代码:

复制代码
$dsn = 'pgsql:dbname=' . $config['database'] . ';host=' . $config['hostname'];
//修改为:
$dsn = 'kdb:host=' . $config['hostname'] . ';dbname=' . $config['database'];

3.新增金仓数据库的builder类

进到ThinkPHP项目目录下的vendor\topthink\think-orm\src\db\builder\下,复制Pgsql.php为Kingbase.php,同样修改文件中的类名为Kingbase。

复制代码
/**
 * Kingbase数据库驱动
 */
class Kingbase extends Builder

其他代码不需要修改。

4.ThinkPHP配置文件

三处mysql都修改为kingbase:

复制代码
return [
    // 默认使用的数据库连接配置
    'default'         => env('database.driver', 'kingbase'),

......

// 数据库连接配置信息
    'connections'     => [
        'kingbase' => [
            // 数据库类型
            'type'            => env('database.type', 'kingbase'),
            // 服务器地址
            'hostname'        => env('database.hostname', 'localhost'),
            // 数据库名
            'database'        => env('database.database', 'TEST'),
            // 用户名
            'username'        => env('database.username', 'SYSTEM'),
            // 密码
            'password'        => env('database.password', '123456'),
            // 端口
            'hostport'        => env('database.hostport', '54321'),
            // 数据库连接参数
            'params'          => [],
            // 数据库编码默认采用utf8
            'charset'         => env('database.charset', 'utf8'),
            // 数据库表前缀
            'prefix'          => env('database.prefix', ''),

......

        // 更多的数据库配置信息
    ],
];

到此处,和其他文章介绍的方案都一样,现在介绍重点,重点就在这个执行的sql语句上,这个语句执行了很多次都不成功,不是提示table_msg函数不存在,就是其他的一些错误,后来在KStudio中单独创建各个函数,依次排除问题解决。

现在分享3个函数的创建语句,需要到对应的模式下,新建查询进行导入:

复制代码
CREATE OR REPLACE FUNCTION public .pgsql_type(a_type  varchar )  RETURNS varchar AS
DECLARE
v_type  varchar ;
BEGIN
     IF a_type= 'int8' THEN
          v_type:= 'bigint' ;
     ELSIF a_type= 'int4' THEN
          v_type:= 'integer' ;
     ELSIF a_type= 'int2' THEN
          v_type:= 'smallint' ;
     ELSIF a_type= 'bpchar' THEN
          v_type:= 'char' ;
ELSE
          v_type:=a_type;
END IF;
RETURN v_type;
END

复制代码
CREATE OR REPLACE FUNCTION public .table_msg(a_schema_name  varchar , a_table_name  varchar )  RETURNS SETOF tablestruct  AS
DECLARE
v_ret  public .tablestruct;

v_oid oid;

v_sql text;

v_rec RECORD;

v_key  varchar ;

BEGIN
    SELECT
    pg_class.oid  INTO v_oid
    FROM
    pg_class
INNER JOIN pg_namespace  ON
    (
        pg_class.relnamespace = pg_namespace.oid
            AND lower (pg_namespace.nspname) = a_schema_name
    )
    WHERE
    pg_class.relname = a_table_name;

IF  NOT FOUND  THEN
         RETURN ;
END IF;

v_sql =  '
     SELECT
           sys_attribute.attname AS fields_name,
           sys_attribute.attnum AS fields_index,
           pgsql_type(sys_type.typname::varchar) AS fields_type,
           sys_attribute.atttypmod-4 as fields_length,
           CASE WHEN sys_attribute.attnotnull THEN ' 'not null' '
           ELSE ' '' '
           END AS fields_not_null,
           sys_attrdef.adbin AS fields_default,
           sys_description.description AS fields_comment 
     FROM
           sys_attribute 
           INNER JOIN sys_class ON sys_attribute.attrelid = sys_class.oid 
           INNER JOIN sys_type ON sys_attribute.atttypid = sys_type.oid 
           LEFT OUTER JOIN sys_attrdef ON sys_attrdef.adrelid = sys_class.oid AND sys_attrdef.adnum = sys_attribute.attnum 
           LEFT OUTER JOIN sys_description ON sys_description.objoid = sys_class.oid AND sys_description.objsubid = sys_attribute.attnum
     WHERE
           sys_attribute.attnum > 0 
           AND attisdropped <> ATTISLOCAL 
ORDER BY sys_attribute.attnum' ;

FOR v_rec  IN EXECUTE v_sql LOOP
         v_ret.fields_name = v_rec.fields_name;

v_ret.fields_type = v_rec.fields_type;

IF v_rec.fields_length > 0  THEN
            v_ret.fields_length := v_rec.fields_length;
ELSE
            v_ret.fields_length :=  NULL ;
END IF;

v_ret.fields_not_null = v_rec.fields_not_null;

v_ret.fields_default = v_rec.fields_default;

v_ret.fields_comment = v_rec.fields_comment;

SELECT
    constraint_name  INTO v_key
FROM
    information_schema.key_column_usage
WHERE
    table_schema = a_schema_name
    AND table_name = a_table_name
    AND column_name = v_rec.fields_name;

IF FOUND  THEN
            v_ret.fields_key_name = v_key;
ELSE
            v_ret.fields_key_name =  '' ;
END IF;

RETURN NEXT v_ret;
END LOOP;

RETURN ;
END

复制代码
CREATE OR REPLACE FUNCTION public .table_msg(a_table_name  varchar )  RETURNS SETOF tablestruct  AS
DECLARE
v_ret tablestruct;
BEGIN
FOR v_ret  IN SELECT *  FROM table_msg( 'public' ,a_table_name) LOOP
    RETURN NEXT v_ret;
END LOOP;
    RETURN ;
END

成功导入3个函数后,在函数项下会出现3个函数,如图:

完成此步骤后:可以在Controller控制器中执行如下代码测试:

复制代码
try {
            $data =\app\home\model\User::select();
            dump( $data );
        } catch (\Exception  $e ) {
            dump( $e ->getMessage());
        }


        \app\home\model\User::create([ "user_name" => "123456" ,
            "user_pwd" => "123456" ,
            "mobile" => "abc" ,
            "full_name" => "abc" ,
        ]);
复制代码
 
相关推荐
倔强的石头1062 天前
时序数据时代的“存储与分析困局”解析及金仓解决方案
时序数据库·kingbase·金仓数据库
主公不搬砖6 天前
Nacos 2.5.2 国产信创 kingbase适配
java·docker·nacos·信创·kingbase·国产适配
king_harry7 天前
金仓数据库KingbaseES中WalMiner接口使用
数据库·kingbase·walminer
用户14644605033797 天前
PHP 多维数组处理利器:array_column() 用法详解
php·thinkphp
倔强的石头1067 天前
【金仓数据库】ksql 指南(六)—— 创建与管理用户和权限(KingbaseES 安全控制核心)
数据库·oracle·kingbase
施嘉伟7 天前
KSQL Developer 测试记录
数据库·kingbase
用户30745969820712 天前
ThinkPHP 6.0 多应用模式下的中间件机制详解
后端·thinkphp
倔强的石头10618 天前
【金仓数据库】ksql 指南(五) —— 创建与管理索引和视图(KingbaseES 查询优化核心)
数据库·oracle·kingbase
一个天蝎座 白勺 程序猿21 天前
破局困境:Oracle迁移金仓KingbaseES数据库的深度实践
数据库·sql·oracle·kingbase·kingbasees·金仓数据库
倔强的石头10621 天前
金仓数据库 MongoDB 兼容:多模融合下的架构之道与实战体验
数据库·mongodb·架构·kingbase