3

在 postgres 9.1 中,我想创建一个函数,它接受一个索引名称、一个表名称和可变数量的列,构造一个索引,然后做一些其他的事情。

我目前的方法是使用 plpgsql 并构造一个动态命令来执行。quote_ident但是,当我试图用来保护所有标识符时,我被绊倒了。到目前为止的代码:

CREATE OR REPLACE FUNCTION my_create_index(indexname text, tablename text, VARIADIC arr text[]) RETURNS void AS $$
  DECLARE
    command_string text;
  BEGIN
    command_string := 'CREATE INDEX ' || quote_ident(indexname) || ' ON ' ||
         quote_ident(tablename) || ' (' ||
         format(repeat('%I ', array_length($3, 1)), VARIADIC $3) ||
         ')';

    -- display the string
    RAISE NOTICE '%', command_string;

    -- execute the string
    EXECUTE command_string;

    -- (do other stuff)
  END;
$$ LANGUAGE plpgsql;

传递一个列名时,代码似乎是成功的,但有两个或更多时,我收到以下错误:

ERROR:  too few arguments for format

我究竟做错了什么?(大概是format我使用或使用的东西VARIADIC。)

谢谢!

4

2 回答 2

4

您通常不会同时使用formatquote_identformat足够聪明,可以做 identifer 引用它的自我;您在表达的一部分中展示了自己,同时在quote_ident其他地方使用了不必要的连接和调用。

但是,我看到format与使用VARIADIC数组参数调用相同的问题,我怀疑您发现了一个错误。

这是一个解决方法,直到我发现发生了什么:

command_string := format('CREATE INDEX %I ON %I (%s)', 
    indexname, tablename, (
      SELECT string_agg(quote_ident(x), ', ') 
      FROM unnest($3) x
    )
);

请注意,在您的原始代码中,'%I '应该是'%I, '.

是的,错误已确认,并且之前已报告过,但看起来从未被检查过。concat和中存在相同的错误concat_ws。这些函数无法检查VARIADIC参数标志。

观察:

regress=> SELECT format('%I', VARIADIC ARRAY['b','c','d']);
  format   
-----------
 "{b,c,d}"
(1 row)

regress=> SELECT format('%I', 'b','c','d');
 format 
--------
 b
(1 row)

regress=> SELECT format('%I, %I, %I', VARIADIC ARRAY['b','c','d']);
ERROR:  too few arguments for format

我能想到的唯一解决方法是避免使用它们(如上所示)或使用EXECUTE动态构造函数调用。在这种情况下format完全是多余的,所以我只需将上面的子查询与unnest.

我会尝试在 PostgreSQL 邮件列表中追查这个问题,但是下周我会忙得不可开交,所以如果你没有看到这个问题,请戳我或在 pgsql-bugs 上发帖,并自行返回这个问题的链接下周中的后续行动。

于 2012-11-23T05:12:36.080 回答
3

您现在不能在格式函数中使用 VARIADIC 参数 :(。这是一个已知错误,将在 PostgreSQL 9.3 中修复(我希望)。您可以尝试使用补丁http://archives.postgresql.org/message-id/ CAFj8pRDZc7wG1ewnmqUWkjDsB78Pu=Oj_WZ8_CS7qJUCKRUNmQ@mail.gmail.com

于 2012-11-23T10:06:20.403 回答