且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在PostgreSQL中将bytea转换为双精度

更新时间:2023-11-07 18:38:46

好,我找到了答案。在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。

Ok, I found an answer. In PostgreSQL, you can write functions using Python. In order to enable the use of Python, you have to install the specific version of Python needed by your installation of PostgreSQL and have it available in the PATH environment variable. You can find which version of Python your installation of PostgreSQL needs by looking at the installation notes. I'm currently using PostgreSQL 9.6.5 on Windows and it calls for Python 3.3. I initially tried the latest Python 3.6, but it wouldn't work. I settled with the latest Python 3.3 for Windows, which is 3.3.5.

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

After installing Python, you enable it in PostgreSQL by executing CREATE EXTENSION plpython3u; on your database as documented here https://www.postgresql.org/docs/current/static/plpython.html. From there, you can write any function with Python bodies.

对于我的具体情况,是将 bytea 转换为 double precision [] 然后,我编写了以下函数:

For my specific case to convert from bytea to double precision[] and back, I wrote the following functions:

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$;

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

In my case, all the doubles are stored in little endian, so I use <. I also cache the import of the struct module in the global dictionary as described in https://***.com/a/15025425/5274457. I used GD instead of SD because I want the import available in other functions I may write. For information about GD and SD, see https://www.postgresql.org/docs/current/static/plpython-sharing.html.

要了解它的作用,知道我数据库中的blob以小端序存储,

To see it in action knowing the blobs in my database are stored as little endian,

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'用小尾数法表示。

where 'efbeaddeefbeadde' is 'deadbeefdeadbeef' in little endian.