pgsql数据库多schema支持问题
根据文档所述,在使用pgsql之前需要导入/db/connector/pgsql.sql文件(postgres12以上版本,则使用 /db/connector/pgsql12.sql),查看源码后发现存在以a_schema_name+a_table_name双参数获取表数据的table_msg函数,以及重载后单入参a_table_name的table_msg函数。
但是重载后单入参a_table_name的table_msg函数只获取public模式下的表数据。但查看/db/connector/Pgsql.php源代码第63行
$sql = 'select fields_name as "field",fields_type as "type",fields_not_null as "null",fields_key_name as "key",fields_default as "default",fields_default as "extra" from table_msg(\'' . $tableName . '\');';
发现该处仅使用了单入参a_table_name的table_msg函数进行获取,top-think/think-orm是否可以针对pgsql支持schema多模式。
因为top-think/think-orm仅支持public单模式,如果强行使用多模式,会导致无法获取非public模式表数据,以及无法更改表数据等问题,我尝试将pgsql.sql文件里的单入参table_msg函数:
---重载一个函数
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 '获得表信息';
修改为:
---重载一个函数
CREATE OR REPLACE FUNCTION "public"."table_msg" (a_table_name varchar) RETURNS SETOF "public"."tablestruct" AS
$body$
DECLARE
v_ret tablestruct;
v_schema varchar;
v_table varchar;
BEGIN
IF position('.' IN a_table_name) > 0 THEN
v_schema := split_part(a_table_name, '.', 1);
v_table := split_part(a_table_name, '.', 2);
ELSE
v_schema := 'public'; -- 默认模式为 public
v_table := a_table_name;
END IF;
FOR v_ret IN SELECT * FROM table_msg(v_schema,v_table) 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 '获得表信息';
上述改动将支持多schema方案,当需要使用多schema,可以将Model的表名进行调整:
protected $name = 'schema.表名';
如果不进行改动,仍然默认为public模式