| 137 | | def query(self, query, *args, **kwargs): |
|---|
| 138 | | self._row_desc = self.c.query(query) |
|---|
| | 137 | def query(self, query, *args): |
|---|
| | 138 | self._row_desc = self.c.extended_query('', '', query, args) |
|---|
| | 139 | #self._row_desc = self.c.query(query) |
|---|
| | 220 | class Parse(object): |
|---|
| | 221 | def __init__(self, ps, qs, types): |
|---|
| | 222 | self.ps = ps |
|---|
| | 223 | self.qs = qs |
|---|
| | 224 | self.types = [Types.pg_type_id(x) for x in types] |
|---|
| | 225 | |
|---|
| | 226 | def serialize(self): |
|---|
| | 227 | val = self.ps + "\x00" + self.qs + "\x00" |
|---|
| | 228 | val = val + struct.pack("!h", len(self.types)) |
|---|
| | 229 | for oid in self.types: |
|---|
| | 230 | val = val + struct.pack("!i", oid) |
|---|
| | 231 | val = struct.pack("!i", len(val) + 4) + val |
|---|
| | 232 | val = "P" + val |
|---|
| | 233 | return val |
|---|
| | 234 | |
|---|
| | 235 | class Bind(object): |
|---|
| | 236 | def __init__(self, portal, ps, in_fc, params, out_fc): |
|---|
| | 237 | self.portal = portal |
|---|
| | 238 | self.ps = ps |
|---|
| | 239 | self.in_fc = in_fc |
|---|
| | 240 | self.params = [] |
|---|
| | 241 | for i in range(len(params)): |
|---|
| | 242 | if len(self.in_fc) == 0: |
|---|
| | 243 | fc = 0 |
|---|
| | 244 | elif len(self.in_fc) == 1: |
|---|
| | 245 | fc = self.in_fc[0] |
|---|
| | 246 | else: |
|---|
| | 247 | fc = self.in_fc[i] |
|---|
| | 248 | self.params.append(Types.pg_value(params[i], fc)) |
|---|
| | 249 | self.out_fc = out_fc |
|---|
| | 250 | |
|---|
| | 251 | def serialize(self): |
|---|
| | 252 | val = self.portal + "\x00" + self.ps + "\x00" |
|---|
| | 253 | val = val + struct.pack("!h", len(self.in_fc)) |
|---|
| | 254 | for fc in self.in_fc: |
|---|
| | 255 | val = val + struct.pack("!h", fc) |
|---|
| | 256 | val = val + struct.pack("!h", len(self.params)) |
|---|
| | 257 | for param in self.params: |
|---|
| | 258 | val = val + struct.pack("!i", len(param)) + param |
|---|
| | 259 | val = val + struct.pack("!h", len(self.out_fc)) |
|---|
| | 260 | for fc in self.out_fc: |
|---|
| | 261 | val = val + struct.pack("!h", fc) |
|---|
| | 262 | val = struct.pack("!i", len(val) + 4) + val |
|---|
| | 263 | val = "B" + val |
|---|
| | 264 | return val |
|---|
| | 265 | |
|---|
| | 266 | class Describe(object): |
|---|
| | 267 | def __init__(self, typ, name): |
|---|
| | 268 | if len(typ) != 1: |
|---|
| | 269 | raise InternalError("Describe typ must be 1 char") |
|---|
| | 270 | self.typ = typ |
|---|
| | 271 | self.name = name |
|---|
| | 272 | |
|---|
| | 273 | def serialize(self): |
|---|
| | 274 | val = self.typ + self.name + "\x00" |
|---|
| | 275 | val = struct.pack("!i", len(val) + 4) + val |
|---|
| | 276 | val = "D" + val |
|---|
| | 277 | return val |
|---|
| | 278 | |
|---|
| | 279 | class DescribePortal(Describe): |
|---|
| | 280 | def __init__(self, name): |
|---|
| | 281 | Protocol.Describe.__init__(self, "P", name) |
|---|
| | 282 | |
|---|
| | 283 | class DescribePreparedStatement(Describe): |
|---|
| | 284 | def __init__(self, name): |
|---|
| | 285 | Protocol.Describe.__init__(self, "S", name) |
|---|
| | 286 | |
|---|
| | 287 | class Flush(object): |
|---|
| | 288 | def serialize(self): |
|---|
| | 289 | return 'H\x00\x00\x00\x04' |
|---|
| | 290 | |
|---|
| | 509 | def extended_query(self, portal, statement, qs, params): |
|---|
| | 510 | self.verifyState("ready") |
|---|
| | 511 | self._send(Protocol.Parse(statement, qs, [type(x) for x in params])) |
|---|
| | 512 | self._send(Protocol.Bind(portal, statement, (1,), params, (1,))) |
|---|
| | 513 | self._send(Protocol.DescribePortal(portal)) |
|---|
| | 514 | self._send(Protocol.Flush()) |
|---|
| | 515 | while 1: |
|---|
| | 516 | msg = self._read_message() |
|---|
| | 517 | if isinstance(msg, Protocol.ParseComplete): |
|---|
| | 518 | # ok, good. |
|---|
| | 519 | pass |
|---|
| | 520 | elif isinstance(msg, Protocol.BindComplete): |
|---|
| | 521 | # good news everybody! |
|---|
| | 522 | pass |
|---|
| | 523 | elif isinstance(msg, Protocol.RowDescription): |
|---|
| | 524 | return msg |
|---|
| | 525 | elif isinstance(msg, Protocol.ErrorResponse): |
|---|
| | 526 | raise msg.createException() |
|---|
| | 527 | else: |
|---|
| | 528 | raise InternalError("Unexpected response msg %r" % (msg)) |
|---|
| | 529 | |
|---|
| 461 | | def convert(data, description): |
|---|
| | 566 | def pg_type_id(typ): |
|---|
| | 567 | data = Types.py_types.get(typ) |
|---|
| | 568 | if data == None: |
|---|
| | 569 | raise NotSupportedError("type %r not mapped to pg type" % typ) |
|---|
| | 570 | type_oid, func_txt, func_bin = data |
|---|
| | 571 | return type_oid |
|---|
| | 572 | pg_type_id = staticmethod(pg_type_id) |
|---|
| | 573 | |
|---|
| | 574 | def pg_value(v, fc): |
|---|
| | 575 | typ = type(v) |
|---|
| | 576 | data = Types.py_types.get(typ) |
|---|
| | 577 | if data == None: |
|---|
| | 578 | raise NotSupportedError("type %r not mapped to pg type" % typ) |
|---|
| | 579 | type_oid, func_txt, func_bin = data |
|---|
| | 580 | if fc == 0: |
|---|
| | 581 | func = func_txt |
|---|
| | 582 | else: |
|---|
| | 583 | func = func_bin |
|---|
| | 584 | if func == None: |
|---|
| | 585 | raise NotSupportedError("type %r, format code %r not converted" % (typ, fc)) |
|---|
| | 586 | return func(v) |
|---|
| | 587 | pg_value = staticmethod(pg_value) |
|---|
| | 588 | |
|---|
| | 589 | def py_value(data, description): |
|---|
| | 590 | type_oid = description['type_oid'] |
|---|