mac-docker-php容器连接mac中的pgsql数据库失败以及出现table_msg存错误时的解决方法

以php中的thinkphp 5.1为例,php容器连接mac中的pgsql数据库失败时,出现如下错误

[7] PDOException in Connection.php line 528
SQLSTATE[08006] [7] could not connect to server: Connection refused
Is the server running on host "localhost" (127.0.0.1) and accepting
TCP/IP connections on port 5432?

解决:以thinkphp 5.1为例,只需把 database.php 中的 hostname 改为 host.docker.internal 即可,然后,thinkphp 就能访问到数据库了。

return [
    // 数据库类型
    'type'            => 'pgsql',
    // 服务器地址
    'hostname'        => 'host.docker.internal'
];

如果可以访问后,再出现 table_msg(unknown) 如下错误时

SQLSTATE[42883]: Undefined function: 7 ERROR: function table_msg(unknown) does not exist
LINE 1: ...fault as "default",fields_default as "extra" from table_msg(...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.

解决:在数据库中执行如下sql即可(因为 table_msg 函数需要用户自己定义)

sql 复制代码
CREATE OR REPLACE FUNCTION pgsql_type(a_type varchar) RETURNS varchar AS  
$BODY$  
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;  
$BODY$  
LANGUAGE PLPGSQL;  
  
CREATE TYPE "public"."tablestruct" AS (  
  "fields_key_name" varchar(100),  
  "fields_name" VARCHAR(200),  
  "fields_type" VARCHAR(20),  
  "fields_length" BIGINT,  
  "fields_not_null" VARCHAR(10),  
  "fields_default" VARCHAR(500),  
  "fields_comment" VARCHAR(1000)  
);  
  
CREATE OR REPLACE FUNCTION "public"."table_msg" (a_schema_name varchar, a_table_name varchar) RETURNS SETOF "public"."tablestruct" AS  
$body$  
DECLARE  
     v_ret tablestruct;  
     v_oid oid;  
     v_sql varchar;  
     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  
           pg_attribute.attname AS fields_name,  
           pg_attribute.attnum AS fields_index,  
           pgsql_type(pg_type.typname::varchar) AS fields_type,  
           pg_attribute.atttypmod-4 as fields_length,  
           CASE WHEN pg_attribute.attnotnull  THEN ''not null''  
           ELSE ''''  
           END AS fields_not_null,  
           pg_attrdef.adsrc AS fields_default,  
           pg_description.description AS fields_comment  
     FROM  
           pg_attribute  
           INNER JOIN pg_class  ON pg_attribute.attrelid = pg_class.oid  
           INNER JOIN pg_type   ON pg_attribute.atttypid = pg_type.oid  
           LEFT OUTER JOIN pg_attrdef ON pg_attrdef.adrelid = pg_class.oid AND pg_attrdef.adnum = pg_attribute.attnum  
           LEFT OUTER JOIN pg_description ON pg_description.objoid = pg_class.oid AND pg_description.objsubid = pg_attribute.attnum  
     WHERE  
           pg_attribute.attnum > 0  
           AND attisdropped <> ''t''  
           AND pg_class.oid = ' || v_oid || '  
     ORDER BY pg_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;  
$body$  
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;  
  
COMMENT ON FUNCTION "public"."table_msg"(a_schema_name varchar, a_table_name varchar)  
IS '获得表信息';  
  
---重载一个函数  
CREATE OR REPLACE FUNCTION "public"."table_msg" (a_table_name varchar) RETURNS SETOF "public"."tablestruct" AS  
$body$  
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;  
$body$  
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;  
  
COMMENT ON FUNCTION "public"."table_msg"(a_table_name varchar)  
IS '获得表信息'; 
相关推荐
gxhlh5 小时前
局域网中 Windows 与 Mac 互相远程连接的最佳方案
windows·macos
宏基骑士5 小时前
mac 电脑上安装adb命令
macos·adb
不会飞的小龙人8 小时前
Docker Compose创建镜像服务
linux·运维·docker·容器·镜像
不会飞的小龙人8 小时前
Docker基础安装与使用
linux·运维·docker·容器
张3蜂8 小时前
docker Ubuntu实战
数据库·ubuntu·docker
事业运财运爆棚9 小时前
Laravel 请求接口 调用2次
php·laravel
寰宇软件10 小时前
PHP CRM售后系统小程序
微信小程序·小程序·vue·php·uniapp
Again_acme11 小时前
20250118面试鸭特训营第26天
服务器·面试·php
水银嘻嘻12 小时前
【Mac】Python相关知识经验
开发语言·python·macos
ac-er888812 小时前
Yii框架中的多语言支持:如何实现国际化
android·开发语言·php