1

我正在编写一个使用 postgresql 数据库的 python3 程序,我使用 py-postgresql: http://python.projects.postgresql.org/作为数据库驱动程序。一张表使用 inet 类型存储 IP 地址。

我创建了以下准备好的语句:

aID = db.prepare('SELECT id FROM a_records WHERE ip = $1 LIMIT 1')

调用 aID(ip) 时出现以下错误:

(ip 是一个 python 字符串)

 File "/usr/local/lib/python3.1/dist-packages/postgresql/driver/pq3.py", line
1517, in __call__
    c = SingleXactFetch(self, parameters)
  File "/usr/local/lib/python3.1/dist-packages/postgresql/driver/pq3.py", line
837, in __init__
    Output.__init__(self, '')
  File "/usr/local/lib/python3.1/dist-packages/postgresql/driver/pq3.py", line
622, in __init__
    self._init()
  File "/usr/local/lib/python3.1/dist-packages/postgresql/driver/pq3.py", line
854, in _init
    STEP()
  File "/usr/local/lib/python3.1/dist-packages/postgresql/driver/pq3.py", line
2612, in _pq_step
    self.typio.raise_error(x.error_message, cause = getattr(x, 'exception', Non
e))
  File "/usr/local/lib/python3.1/dist-packages/postgresql/driver/pq3.py", line
507, in raise_error
    self.raise_server_error(error_message, **kw)
  File "/usr/local/lib/python3.1/dist-packages/postgresql/driver/pq3.py", line
498, in raise_server_error
    raise server_error
postgresql.exceptions.BinaryRepresentationError: invalid address family in exte
rnal "inet" value
  CODE: 22P03
  LOCATION: File 'network.c', line 218, in network_recv from SERVER
RESULT:
  type: SingleXactFetch
  parameters: ('139.78.113.1',)
STATEMENT: [prepared]
  sql_parameter_types: ['pg_catalog.inet']
  results: (id INTEGER)
  statement_id: py:0x2ff9a50
  string: SELECT id FROM a_records WHERE ip = $1 LIMIT 1
CONNECTION: [idle]
  client_address: 127.0.0.1/32
  client_port: 51563
  version:
    PostgreSQL 8.4.7 on x86_64-pc-linux-gnu, compiled by GCC gcc-4.4.real (Debi
an 4.4.5-8) 4.4.5, 64-bit
CONNECTOR: [IP4] pq://python:***@127.0.0.1:5432/vdz
  category: None
DRIVER: postgresql.driver.pq3.Driver

谁能帮我调试一下并弄清楚为什么 postgresql 不喜欢 inet 数据?

谢谢!

4

3 回答 3

1

I've been having this problem all day, and I could not find any solution, so obviously I found the solution on my own a few minutes after posting here.

I need to replace $1 with inet($1::varchar), it seems that postgresql does not like it being a string when converting to an inet value, and you must typecast it as a varchar, and then turn the value into an inet variable.

So, the working line is:

aID = db.prepare('SELECT id FROM a_records WHERE ip = inet($1::varchar) LIMIT 1')

Can anyone explain why this is, and why it wont work the way I tried to at first?

Thanks!

于 2011-05-17T05:17:04.000 回答
1

@mrlanrat,这是因为 python 库将您的参数作为 TEXT 数据类型发送,但 PostgreSQL 需要 INET 数据类型。您的示例更改了参数,以便 PostgreSQL 期望 TEXT 数据类型,然后将其转换为 INET 数据类型。我知道 psycopg2 支持 INET 数据类型,但我很确定当前版本的 py-postgresql 不支持该数据类型(截至 2011 年 5 月 19 日)。这意味着您有三个选择:

  1. py-postgresql 需要添加对 INET 数据类型的支持
  2. 您可以传入 TEXT 类型的数据,然后将其转换为服务器上的 INET
  3. 切换到 psycopg2,它确实支持 INET 数据类型。

http://initd.org/psycopg/docs/extras.html#inet-data-type

于 2011-05-19T17:52:49.527 回答
0

您应该将字符串显式转换为 inet 数据类型。

aID = db.prepare('SELECT id FROM a_records WHERE ip = inet($1) LIMIT 1')
于 2011-05-17T05:07:45.490 回答