7

我有一个数据库,其中一个表存储bytea从另一个系统收集的各种通用数据的 blob ()。该bytea字段可以包含任何内容。为了知道如何解释数据,表格还有一个格式字段。我编写了一个 Java 应用程序来从数据库中读取bytea字段作为 a byte[],然后我可以通过使用和各种视图(、等)轻松地将其转换为double[]int[]格式字段所说的任何内容。ByteBufferDoubleBufferIntBuffer

现在,我需要在触发器函数中对数据库本身的数据进行一些操作,以保持与另一个表的完整性。我几乎可以找到任何可以想象的数据类型的转换,但我找不到任何从bytea(甚至bitdouble precision来回的东西。Abytea可以分解,转换为位,然后转换为intor bigint,但不是 a double precision。例如,x'deadbeefdeadbeef'::bit(64)::bigint将转换为-2401053088876216593没有问题,但x'deadbeefdeadbeef'::bit(64)::double precision失败并显示“错误:无法将类型位转换为双精度”,而不是给出 IEEE 754 答案-1.1885959257070704E148

我找到了这个答案https://stackoverflow.com/a/11661849/5274457,它基本上实现了 IEEE 标准将位转换为双精度,但是 PostgreSQL 中真的没有基本的转换功能可以做到这一点吗?double precision另外,当我完成数据操作并需要更新表格时,我还需要从to倒退bytea,而这个答案没有提供。

有任何想法吗?

4

1 回答 1

2

好的,我找到了答案。在 PostgreSQL 中,您可以使用 Python 编写函数。为了启用 Python 的使用,您必须安装 PostgreSQL 安装所需的特定 Python 版本,并使其在 PATH 环境变量中可用。您可以通过查看安装说明找到安装 PostgreSQL 所需的 Python 版本。我目前在 Windows 上使用 PostgreSQL 9.6.5,它需要 Python 3.3。我最初尝试了最新的 Python 3.6,但它不起作用。我选择了最新的适用于 Windows 的 Python 3.3,即 3.3.5。

CREATE EXTENSION plpython3u;安装 Python 后,您可以通过在您的数据库上执行它在 PostgreSQL 中启用它,如此处记录的https://www.postgresql.org/docs/current/static/plpython.html。从那里,您可以使用 Python 主体编写任何函数。

对于我的具体情况来回转换byteadouble precision[]我编写了以下函数:

CREATE FUNCTION bytea_to_double_array(b bytea)
    RETURNS double precision[]
    LANGUAGE 'plpython3u'
AS $BODY$
  if 'struct' in GD:
    struct = GD['struct']
  else:
    import struct
    GD['struct'] = struct

  return struct.unpack('<' + str(int(len(b) / 8)) + 'd', b)
$BODY$;

CREATE FUNCTION double_array_to_bytea(dblarray double precision[])
    RETURNS bytea
    LANGUAGE 'plpython3u'
AS $BODY$
  if 'struct' in GD:
    struct = GD['struct']
  else:
    import struct
    GD['struct'] = struct

  # dblarray here is really a list.
  # PostgreSQL passes SQL arrays as Python lists
  return struct.pack('<' + str(int(len(dblarray))) + 'd', *dblarray)
$BODY$;

在我的例子中,所有的双打都存储在小端,所以我使用<. 我还将struct模块的导入缓存在全局字典中,如https://stackoverflow.com/a/15025425/5274457中所述。我使用 GD 而不是 SD,因为我希望可以在我可能编写的其他函数中使用导入。有关 GD 和 SD 的信息,请参阅https://www.postgresql.org/docs/current/static/plpython-sharing.html

知道我的数据库中的 blob 存储为小端序时,要查看它的实际效果,

SELECT bytea_to_double_array(decode('efbeaddeefbeadde', 'hex')), encode(double_array_to_bytea(array[-1.1885959257070704E148]), 'hex');

我得到的答案是

bytea_to_double_array    | encode
double precision[]       | text
-------------------------+------------------
{-1.18859592570707e+148} | efbeaddeefbeadde

'efbeaddeefbeadde'小端在哪里'deadbeefdeadbeef'

于 2017-09-22T18:23:08.210 回答