ETJava Beta | Java    注册   登录
  • 搜索:
  • ThinkPHP6支持金仓数据库(Kingbase)解决无法使用模型查询问题

    发表于      阅读(1)     博客类别:Crawler     转自:https://www.cnblogs.com/lanfengye/p/18337128
    如有侵权 请联系我们删除  (页面底部联系我们)  

    参考了很多前人的文章,最后只支持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" ,
            ]);