如何在PL / TCL中访问PostgreSQL数组

时间:2013-07-27 20:25:33

标签: postgresql tcl

如何访问传入pl / tcl函数的数组?参数不应该变成列表吗?在下面的代码中,无论输入是什么,它都会打印“1”,例如“select foobar(array [1,2,3]);”

我感兴趣的是构建自定义聚合,它使用数组来保持调用之间的状态。

编辑:

这是一个新功能:

create function foobar(int[]) returns int[] as $$
    elog INFO "$1, [llength $1]"
    return $1
$$ language pltcl;

这是调用和输出,它显示了进出函数的数组:

postgis20=# select (array[1,2,3])[1];
 array
-------
     1
(1 row)

postgis20=# select foobar(array[1,2,3]);
INFO:  {1,2,3}, 1
 foobar
---------
 {1,2,3}
(1 row)

postgis20=# select (foobar(array[1,2,3]))[1];
INFO:  {1,2,3}, 1
 foobar
--------
      1
(1 row)

谢谢!

1 个答案:

答案 0 :(得分:1)

documentation有点不可知,但它包括:

  

提供给PL / Tcl函数代码的参数值只是转换为文本形式的输入参数(就像它们已由SELECT语句显示一样)。相反,return命令将接受函数声明的返回类型的可接受输入格式的任何字符串。因此,在PL / Tcl函数中,所有值都只是文本字符串。

因此来自Tcl的PoV的数组值将是{1,2,3}或类似的东西。其他一切都是在序列化和Tcl列表之间进行转换。 (所有这些对于其他类型的数值数组也可以正常工作,但如果你做了字符或字符串数​​组会很危险,因为分隔符字符可以出现在其中。当然,在这种情况下,我也认为你在做首先有点不对劲......)

处理PostgreSQL int[]数组

要从这样的事物中提取整数,我们会这样做:

set tclListOfValues [split [string trim $1 "{}"] ","]

之后,您可以使用llengthlindex以及foreach等。反向操作,将Tcl列表(假设为整数)转换为int[]以便返回:

return \{[join $tclListOfValues ","]\}

处理嵌套的PostgreSQL数组

如果您需要访问嵌套数组,事情会变得更加尴尬。问题在于它是一个两级分割,最好通过在外部string map之前使用split应用一些聪明的魔法来实现:

set listOfLists {}
foreach innerArray [split [string map {"\},\{" "\u0000"} [string trim $1 "{}"]] "\u0000"] {
    lappend listOfLists [split $innerArray ","]
}

在Tcl 8.6中,你可以用这样的lmap稍微整齐地做这个(概念上是单行,但是为了清晰起见):

set listOfLists [lmap innerArray \
        [split [string map {"\},\{" "\u0000"} [string trim $1 "{}"]] "\u0000"] {
    split $innerArray ","
}]

反方向:

set resultAccumulator {}
foreach innerList $listOfLists {
    lappend resultAccumulator [join $innerList ","]
}
return \{[join $resultAccumulator "\},\{"]\}

或者再次使用lmap的Tcl 8.6样式:

return \{[join [lmap innerList $listOfLists {join $innerList ","}] "\},\{"]\}