PostgreSQL的占位符模板

时间:2012-09-03 20:10:02

标签: postgresql formatting

我需要一个像

这样的功能
SELECT vformat('Hello %%! Bye %%...', array['John','Maria'], '%%');
-- 'Hello John! Bye Maria...'

向字符串提供占位符(模板),并将相应的输入提供给向量,它返回一个文本。 “占位符标记”是一个自由字符串。

我不能使用pg9.1格式(如sprintf)函数,因为它不允许其他标记而不是'%'(参见例如Python formatter)并且不允许数组参数(参见例如{ {3}})。 使用PostgreSQL 9.0(我认为8.4+)的SIMPLEST解决方案是

CREATE FUNCTION array_zipper_string(anyarray,anyarray) RETURNS text AS $$ 
  -- use with bigger array at left
  SELECT string_agg(t.val||coalesce($2[t.idx],''),'')  
  FROM  (SELECT generate_subscripts($1, 1) AS idx, unnest($1) AS val) AS t;
$$ LANGUAGE SQL IMMUTABLE;

CREATE FUNCTION tpl_positional(text,anyarray,varchar DEFAULT '%%') 
RETURNS text AS $$ 
  SELECT array_zipper_string(string_to_array($1,$3),$2);
$$ LANGUAGE SQL IMMUTABLE;
CREATE FUNCTION tpl_positional(
   text, text, varchar DEFAULT '%%',varchar DEFAULT '|' 
) RETURNS text AS $$ 
  SELECT tpl_positional($1,string_to_array($2,$4),$3);
$$ LANGUAGE SQL IMMUTABLE;

-- TESTING:
SELECT tpl_positional('Hello %%! Bye %%...', 'John|Maria');
SELECT tpl_positional('Hello %%!',array['John']);

有众所周知的(开源)功能这样做吗?

PS:这样做还有更多(!)......我的愿望清单:

  • 来自标准库的开源
  • 可索引占位符选项'Hello %% {1}!再见%% {2} ...'
  • 使用格式化程序的选项,'有%% 2d猴子。'或者'有%% {1 | 2d}个猴子。';

3 个答案:

答案 0 :(得分:2)

如果Python的格式化功能可以满足你的需要,可以通过PL / Python包装它,并使用它。你需要:

CREATE LANGUAGE plpythonu;

...可能需要您安装包含python语言支持的附加软件包或使用--with-python重新编译,具体取决于您安装Pg的方式或您正在使用的软件包。对于我使用Fedora 17软件包,它是yum install postgresql-plpython

您需要签名:

CREATE OR REPLACE FUNCTION my_format(formatstr text, placeholder text, args VARIADIC text) RETURNS text LANGUAGE 'plpythonu' IMMUTABLE AS $$
 .... body here ....
 $$;

请注意使用plpython u 。这里 u 表示“不信任”,即“没有安全模型”。不能限制以不受信任的语言运行的代码,因此服务器只允许超级用户使用这些语言创建函数。必须编写它们,以便在数据库暴露给不太信任的用户时,不会欺骗他们做除作者之外的其他事情。

不幸的是,最后我检查过程语言对数组的处理不是很精彩。请参阅本文底部的depesz文章及其注释。这是可行的,只是笨拙而不是很好。

如果Python的格式功能没有做你想做的事,请考虑Perl。 PL / Perl非常受欢迎,部分原因是与Python不同,它有一个安全模型,并且有plperl的“可信”版本。如果你找不到合适的CPAN模块来做​​你想做的事,我会很惊讶。函数签名将大致相同,只需plperl

请参阅此excellent-as-usual depesz article on plperl and sprintf

答案 1 :(得分:1)

其他可能性是使用 orafce http://postgres.cz/wiki/Oracle_functionality_%28en%29 - 架构''PLVsubst''中的函数完全符合您的要求。 Orafce在redhat,centos存储库中,但通常不会在任何托管上启用。

答案 2 :(得分:0)

PostgreSQL FORMAT()函数根据格式字符串格式化参数。

如果你使用过C编程语言,你会发现FORMAT()函数类似于sprintf()函数。

SELECT FORMAT('Hello, %s','PostgreSQL');

      format
-------------------
 Hello, PostgreSQL
(1 row)

有关详细信息,请参阅http://www.postgresqltutorial.com/postgresql-format/