1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 __author__ = "Mathieu Fenniak"
31
32 import socket
33 import struct
34 import datetime
35 import md5
36 import decimal
37 import threading
38 import time
39
42
43 -class Error(StandardError):
45
48
51
54
57
60
63
66
69
72 self.obj = obj
73 self.func = func
74
77
79 retval = self.func(self.obj)
80 if retval == None:
81 raise StopIteration()
82 return retval
83
85 Warning = Warning
86 Error = Error
87 InterfaceError = InterfaceError
88 InternalError = InternalError
89 DatabaseError = DatabaseError
90 DataError = DataError
91 OperationalError = OperationalError
92 IntegrityError = IntegrityError
93 ProgrammingError = ProgrammingError
94 NotSupportedError = NotSupportedError
95
96 apilevel = "2.0"
97 threadsafety = 3
98 paramstyle = 'format'
99
101
102
103
104
105
106
107
108 state = 0
109 output_query = ""
110 output_args = []
111 if src_style == "numeric":
112 output_args = args
113 elif src_style in ("pyformat", "named"):
114 mapping_to_idx = {}
115 i = 0
116 while 1:
117 if i == len(query):
118 break
119 c = query[i]
120
121 if state == 0:
122 if c == "'":
123 i += 1
124 output_query += c
125 state = 1
126 elif c == '"':
127 i += 1
128 output_query += c
129 state = 2
130 elif c == 'E':
131
132 i += 1
133 if i < len(query) and i > 1 and query[i] == "'":
134 i += 1
135 output_query += "E'"
136 state = 3
137 else:
138 output_query += c
139 elif src_style == "qmark" and c == "?":
140 i += 1
141 param_idx = len(output_args)
142 if param_idx == len(args):
143 raise ProgrammingError("too many parameter fields, not enough parameters")
144 output_args.append(args[param_idx])
145 output_query += "$" + str(param_idx + 1)
146 elif src_style == "numeric" and c == ":":
147 i += 1
148 if i < len(query) and i > 1 and query[i].isdigit():
149 output_query += "$" + query[i]
150 i += 1
151 else:
152 raise ProgrammingError("numeric parameter : does not have numeric arg")
153 elif src_style == "named" and c == ":":
154 name = ""
155 while 1:
156 i += 1
157 if i == len(query):
158 break
159 c = query[i]
160 if c.isalnum():
161 name += c
162 else:
163 break
164 if name == "":
165 raise ProgrammingError("empty name of named parameter")
166 idx = mapping_to_idx.get(name)
167 if idx == None:
168 idx = len(output_args)
169 output_args.append(args[name])
170 idx += 1
171 mapping_to_idx[name] = idx
172 output_query += "$" + str(idx)
173 elif src_style == "format" and c == "%":
174 i += 1
175 if i < len(query) and i > 1:
176 if query[i] == "s":
177 param_idx = len(output_args)
178 if param_idx == len(args):
179 raise ProgrammingError("too many parameter fields, not enough parameters")
180 output_args.append(args[param_idx])
181 output_query += "$" + str(param_idx + 1)
182 elif query[i] == "%":
183 output_query += "%"
184 else:
185 raise ProgrammingError("Only %s and %% are supported")
186 i += 1
187 else:
188 raise ProgrammingError("numeric parameter : does not have numeric arg")
189 elif src_style == "pyformat" and c == "%":
190 i += 1
191 if i < len(query) and i > 1:
192 if query[i] == "(":
193 i += 1
194
195 end_idx = query.find(')', i)
196 if end_idx == -1:
197 raise ProgrammingError("began pyformat dict read, but couldn't find end of name")
198 else:
199 name = query[i:end_idx]
200 i = end_idx + 1
201 if i < len(query) and query[i] == "s":
202 i += 1
203 idx = mapping_to_idx.get(name)
204 if idx == None:
205 idx = len(output_args)
206 output_args.append(args[name])
207 idx += 1
208 mapping_to_idx[name] = idx
209 output_query += "$" + str(idx)
210 else:
211 raise ProgrammingError("format not specified or not supported (only %(...)s supported)")
212 elif query[i] == "%":
213 output_query += "%"
214 else:
215 i += 1
216 output_query += c
217 elif state == 1:
218 output_query += c
219 i += 1
220 if c == "'":
221
222 if i < len(query) and query[i] == "'":
223
224 output_query += query[i]
225 i += 1
226 else:
227 state = 0
228 elif src_style in ("pyformat","format") and c == "%":
229
230 if i < len(query):
231 if query[i] == "%":
232
233 i += 1
234 else:
235 raise ProgrammingError("'%" + query[i] + "' not supported in quoted string")
236 elif state == 2:
237 output_query += c
238 i += 1
239 if c == '"':
240 state = 0
241 elif src_style in ("pyformat","format") and c == "%":
242
243 if i < len(query):
244 if query[i] == "%":
245
246 i += 1
247 else:
248 raise ProgrammingError("'%" + query[i] + "' not supported in quoted string")
249 elif state == 3:
250 output_query += c
251 i += 1
252 if c == "\\":
253
254 if i < len(query) and query[i] == "'":
255 output_query += "'"
256 i += 1
257 elif c == "'":
258 state = 0
259 elif src_style in ("pyformat","format") and c == "%":
260
261 if i < len(query):
262 if query[i] == "%":
263
264 i += 1
265 else:
266 raise ProgrammingError("'%" + query[i] + "' not supported in quoted string")
267
268 return output_query, tuple(output_args)
269 convert_paramstyle = staticmethod(convert_paramstyle)
270
271
276
277 rowcount = property(lambda self: self._getRowCount())
280
281 description = property(lambda self: self._getDescription())
289
290 - def execute(self, operation, args=()):
300
302 for parameters in parameter_sets:
303 self.execute(operation, parameters)
304
309
311 if size == None:
312 size = self.arraysize
313 rows = []
314 for i in range(size):
315 rows.append(self.fetchone())
316 return rows
317
322
325
328
331
336
339
341
342
343
344
345
346
347
348
349 if self.conn == None:
350 raise InterfaceError("connection is closed")
351 self.conn.commit()
352 self.conn.begin()
353
360
363
364 - def connect(user, host=None, unix_sock=None, port=5432, database=None, password=None, socket_timeout=60, ssl=False):
365 return DBAPI.ConnectionWrapper(user=user, host=host,
366 unix_sock=unix_sock, port=port, database=database,
367 password=password, socket_timeout=socket_timeout, ssl=ssl)
368 connect = staticmethod(connect)
369
370 - def Date(year, month, day):
371 return datetime.date(year, month, day)
372 Date = staticmethod(Date)
373
374 - def Time(hour, minute, second):
375 return datetime.time(hour, minute, second)
376 Time = staticmethod(Time)
377
378 - def Timestamp(year, month, day, hour, minute, second):
379 return datetime.datetime(year, month, day, hour, minute, second)
380 Timestamp = staticmethod(Timestamp)
381
383 return DBAPI.Date(*time.localtime(ticks)[:3])
384 DateFromTicks = staticmethod(DateFromTicks)
385
387 return DBAPI.Time(*time.localtime(ticks)[3:6])
388 TimeFromTicks = staticmethod(TimeFromTicks)
389
392 TimestampFromTicks = staticmethod(TimestampFromTicks)
393
396 Binary = staticmethod(Binary)
397
398
399
400
401 STRING = 25
402
403
404 BINARY = 17
405
406
407 NUMBER = 1700
408
409
410 DATETIME = 1114
411
412
413 ROWID = 26
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
440
441
442
443
444
445
446
447
448
449
450
451 row_cache_size = 100
452
453 - def __init__(self, connection, statement, *types):
454 self.c = connection.c
455 self._portal_name = "pg8000_portal_%s_%s" % (id(self.c), id(self))
456 self._statement_name = "pg8000_statement_%s_%s" % (id(self.c), id(self))
457 self._row_desc = None
458 self._cached_rows = []
459 self._command_complete = True
460 self._parse_row_desc = self.c.parse(self._statement_name, statement, types)
461 self._lock = threading.RLock()
462
469
470 row_description = property(lambda self: self._getRowDescription())
472 return self._row_desc.fields
473
474
475
476
477
479 self._lock.acquire()
480 try:
481 if not self._command_complete:
482
483 self._cached_rows = []
484 self.c.close_portal(self._portal_name)
485 self._command_complete = False
486 self._row_desc = self.c.bind(self._portal_name, self._statement_name, args, self._parse_row_desc)
487 if self._row_desc:
488
489
490
491
492
493 self._fill_cache()
494 finally:
495 self._lock.release()
496
498 self._lock.acquire()
499 try:
500 if self._cached_rows:
501 raise InternalError("attempt to fill cache that isn't empty")
502 end_of_data, rows = self.c.fetch_rows(self._portal_name, self.row_cache_size, self._row_desc)
503 self._cached_rows = rows
504 if end_of_data:
505 self._command_complete = True
506 finally:
507 self._lock.release()
508
510 self._lock.acquire()
511 try:
512 if not self._cached_rows:
513 if self._command_complete:
514 return None
515 self._fill_cache()
516 if self._command_complete and not self._cached_rows:
517
518
519
520 return None
521 row = self._cached_rows[0]
522 del self._cached_rows[0]
523 return tuple(row)
524 finally:
525 self._lock.release()
526
527
528
529
530
531
532
534 row = self._fetch()
535 if row == None:
536 return row
537 retval = {}
538 for i in range(len(self._row_desc.fields)):
539 col_name = self._row_desc.fields[i]['name']
540 if retval.has_key(col_name):
541 raise InterfaceError("cannot return dict of row when two columns have the same name (%r)" % (col_name,))
542 retval[col_name] = row[i]
543 return retval
544
545
546
547
548
549
551 row = self._fetch()
552 if row == None:
553 return row
554 return row
555
556
557
558
559
560
561
564
565
566
567
568
569
570
573
574
575
576
577
578
579
580
581
582
583
584
585
586
589 self.connection = connection
590 self._stmt = None
591
592 row_description = property(lambda self: self._getRowDescription())
594 if self._stmt == None:
595 return None
596 return self._stmt.row_description
597
598
599
600
601
602
603
604
608
609
610
611
612
613
614
616 if self._stmt == None:
617 raise ProgrammingError("attempting to read from unexecuted cursor")
618 return self._stmt.read_dict()
619
620
621
622
623
624
626 if self._stmt == None:
627 raise ProgrammingError("attempting to read from unexecuted cursor")
628 return self._stmt.read_tuple()
629
630
631
632
633
634
635
640
641
642
643
644
645
646
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
697 - def __init__(self, user, host=None, unix_sock=None, port=5432, database=None, password=None, socket_timeout=60, ssl=False):
698 self._row_desc = None
699 try:
700 self.c = Protocol.Connection(unix_sock=unix_sock, host=host, port=port, socket_timeout=socket_timeout, ssl=ssl)
701
702 self.c.authenticate(user, password=password, database=database)
703 except socket.error, e:
704 print repr(e)
705 print dir(e)
706 print str(e)
707
708 raise InterfaceError("communication error", e)
709 Cursor.__init__(self, self)
710 self._begin = PreparedStatement(self, "BEGIN TRANSACTION")
711 self._commit = PreparedStatement(self, "COMMIT TRANSACTION")
712 self._rollback = PreparedStatement(self, "ROLLBACK TRANSACTION")
713
714
715
716
717
720
721
722
723
724
727
728
729
730
731
734
735
737
741
743 return struct.pack("!ii", 8, 80877103)
744
746 - def __init__(self, user, database=None):
747 self.user = user
748 self.database = database
749
751 protocol = 196608
752 val = struct.pack("!i", protocol)
753 val += "user\x00" + self.user + "\x00"
754 if self.database:
755 val += "database\x00" + self.database + "\x00"
756 val += "\x00"
757 val = struct.pack("!i", len(val) + 4) + val
758 return val
759
763
765 val = self.qs + "\x00"
766 val = struct.pack("!i", len(val) + 4) + val
767 val = "Q" + val
768 return val
769
772 self.ps = ps
773 self.qs = qs
774 self.type_oids = type_oids
775
777 val = self.ps + "\x00" + self.qs + "\x00"
778 val = val + struct.pack("!h", len(self.type_oids))
779 for oid in self.type_oids:
780
781
782
783 if oid == -1: oid = 705
784 val = val + struct.pack("!i", oid)
785 val = struct.pack("!i", len(val) + 4) + val
786 val = "P" + val
787 return val
788
789 - class Bind(object):
790 - def __init__(self, portal, ps, in_fc, params, out_fc, client_encoding):
791 self.portal = portal
792 self.ps = ps
793 self.in_fc = in_fc
794 self.params = []
795 for i in range(len(params)):
796 if len(self.in_fc) == 0:
797 fc = 0
798 elif len(self.in_fc) == 1:
799 fc = self.in_fc[0]
800 else:
801 fc = self.in_fc[i]
802 self.params.append(Types.pg_value(params[i], fc, client_encoding = client_encoding))
803 self.out_fc = out_fc
804
806 val = self.portal + "\x00" + self.ps + "\x00"
807 val = val + struct.pack("!h", len(self.in_fc))
808 for fc in self.in_fc:
809 val = val + struct.pack("!h", fc)
810 val = val + struct.pack("!h", len(self.params))
811 for param in self.params:
812 if param == None:
813
814 val = val + struct.pack("!i", -1)
815 else:
816 val = val + struct.pack("!i", len(param)) + param
817 val = val + struct.pack("!h", len(self.out_fc))
818 for fc in self.out_fc:
819 val = val + struct.pack("!h", fc)
820 val = struct.pack("!i", len(val) + 4) + val
821 val = "B" + val
822 return val
823
826 if len(typ) != 1:
827 raise InternalError("Close typ must be 1 char")
828 self.typ = typ
829 self.name = name
830
832 val = self.typ + self.name + "\x00"
833 val = struct.pack("!i", len(val) + 4) + val
834 val = "C" + val
835 return val
836
840
844
847 if len(typ) != 1:
848 raise InternalError("Describe typ must be 1 char")
849 self.typ = typ
850 self.name = name
851
853 val = self.typ + self.name + "\x00"
854 val = struct.pack("!i", len(val) + 4) + val
855 val = "D" + val
856 return val
857
861
865
868 return 'H\x00\x00\x00\x04'
869
870 - class Sync(object):
872 return 'S\x00\x00\x00\x04'
873
877
879 val = self.pwd + "\x00"
880 val = struct.pack("!i", len(val) + 4) + val
881 val = "p" + val
882 return val
883
886 self.portal = portal
887 self.row_count = row_count
888
890 val = self.portal + "\x00" + struct.pack("!i", self.row_count)
891 val = struct.pack("!i", len(val) + 4) + val
892 val = "E" + val
893 return val
894
910
912 - def ok(self, conn, user, **kwargs):
914
917 self.salt = "".join(struct.unpack("4c", data))
918
919 - def ok(self, conn, user, password=None, **kwargs):
920 if password == None:
921 raise InterfaceError("server requesting MD5 password authentication, but no password was provided")
922 pwd = "md5" + md5.new(md5.new(password + user).hexdigest() + self.salt).hexdigest()
923 conn._send(Protocol.PasswordMessage(pwd))
924 msg = conn._read_message()
925 if isinstance(msg, Protocol.AuthenticationRequest):
926 return msg.ok(conn, user)
927 elif isinstance(msg, Protocol.ErrorResponse):
928 if msg.code == "28000":
929 raise InterfaceError("md5 password authentication failed")
930 else:
931 raise InternalError("server returned unexpected error %r" % msg)
932 else:
933 raise InternalError("server returned unexpected response %r" % msg)
934
935 authentication_codes = {
936 0: AuthenticationOk,
937 5: AuthenticationMD5Password,
938 }
939
950
960
965
970
975
980
985
989
991 return "<ReadyForQuery %s>" % \
992 {"I": "Idle", "T": "Idle in Transaction", "E": "Idle in Failed Transaction"}[self.status]
993
996 createFromData = staticmethod(createFromData)
997
1005
1007 - def __init__(self, severity, code, msg):
1008 self.severity = severity
1009 self.code = code
1010 self.msg = msg
1011
1013 return "<ErrorResponse %s %s %r>" % (self.severity, self.code, self.msg)
1014
1017
1019 args = {}
1020 for s in data.split("\x00"):
1021 if not s:
1022 continue
1023 elif s[0] == "S":
1024 args["severity"] = s[1:]
1025 elif s[0] == "C":
1026 args["code"] = s[1:]
1027 elif s[0] == "M":
1028 args["msg"] = s[1:]
1029 return Protocol.ErrorResponse(**args)
1030 createFromData = staticmethod(createFromData)
1031
1040
1043 self.fields = fields
1044
1046 count = struct.unpack("!h", data[:2])[0]
1047 data = data[2:]
1048 fields = []
1049 for i in range(count):
1050 null = data.find("\x00")
1051 field = {"name": data[:null]}
1052 data = data[null+1:]
1053 field["table_oid"], field["column_attrnum"], field["type_oid"], field["type_size"], field["type_modifier"], field["format"] = struct.unpack("!ihihih", data[:18])
1054 data = data[18:]
1055 fields.append(field)
1056 return Protocol.RowDescription(fields)
1057 createFromData = staticmethod(createFromData)
1058
1066
1069 self.fields = fields
1070
1072 count = struct.unpack("!h", data[:2])[0]
1073 data = data[2:]
1074 fields = []
1075 for i in range(count):
1076 val_len = struct.unpack("!i", data[:4])[0]
1077 data = data[4:]
1078 if val_len == -1:
1079 fields.append(None)
1080 else:
1081 fields.append(data[:val_len])
1082 data = data[val_len:]
1083 return Protocol.DataRow(fields)
1084 createFromData = staticmethod(createFromData)
1085
1088 self.sslobj = sslobj
1089 - def send(self, data):
1090 self.sslobj.write(data)
1091 - def recv(self, num):
1092 return self.sslobj.read(num)
1093
1095 - def __init__(self, unix_sock=None, host=None, port=5432, socket_timeout=60, ssl=False):
1096 self._client_encoding = "ascii"
1097 if unix_sock == None and host != None:
1098 self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1099 elif unix_sock != None:
1100 self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1101 else:
1102 raise ProgrammingError("one of host or unix_sock must be provided")
1103 if unix_sock == None and host != None:
1104 self._sock.connect((host, port))
1105 elif unix_sock != None:
1106 self._sock.connect(unix_sock)
1107 if ssl:
1108 self._send(Protocol.SSLRequest())
1109 resp = self._sock.recv(1)
1110 if resp == 'S':
1111 self._sock = Protocol.SSLWrapper(socket.ssl(self._sock))
1112 else:
1113 raise InterfaceError("server refuses SSL")
1114 else:
1115
1116 self._sock.settimeout(socket_timeout)
1117 self._state = "noauth"
1118 self._backend_key_data = None
1119 self._sock_lock = threading.Lock()
1120
1122 if self._state != state:
1123 raise InternalError("connection state must be %s, is %s" % (state, self._state))
1124
1128
1130 bytes = ""
1131 while len(bytes) < 5:
1132 tmp = self._sock.recv(5 - len(bytes))
1133 bytes += tmp
1134 if len(bytes) != 5:
1135 raise InternalError("unable to read 5 bytes from socket %r" % bytes)
1136 message_code = bytes[0]
1137 data_len = struct.unpack("!i", bytes[1:])[0] - 4
1138 if data_len == 0:
1139 bytes = ""
1140 else:
1141 bytes = ""
1142 while len(bytes) < data_len:
1143 tmp = self._sock.recv(data_len - len(bytes))
1144 bytes += tmp
1145 assert len(bytes) == data_len
1146 msg = Protocol.message_types[message_code].createFromData(bytes)
1147 if isinstance(msg, Protocol.NoticeResponse):
1148
1149 return self._read_message()
1150 else:
1151 return msg
1152
1179
1180 - def parse(self, statement, qs, types):
1181 self.verifyState("ready")
1182 self._sock_lock.acquire()
1183 try:
1184 type_info = [Types.pg_type_info(x) for x in types]
1185 param_types, param_fc = [x[0] for x in type_info], [x[1] for x in type_info]
1186 self._send(Protocol.Parse(statement, qs, param_types))
1187 self._send(Protocol.DescribePreparedStatement(statement))
1188 self._send(Protocol.Flush())
1189 while 1:
1190 msg = self._read_message()
1191 if isinstance(msg, Protocol.ParseComplete):
1192
1193 pass
1194 elif isinstance(msg, Protocol.ParameterDescription):
1195
1196
1197
1198 pass
1199 elif isinstance(msg, Protocol.NoData):
1200
1201
1202
1203 return (None, param_fc)
1204 elif isinstance(msg, Protocol.RowDescription):
1205 return (msg, param_fc)
1206 elif isinstance(msg, Protocol.ErrorResponse):
1207 raise msg.createException()
1208 else:
1209 raise InternalError("Unexpected response msg %r" % (msg))
1210 finally:
1211 self._sock_lock.release()
1212
1213 - def bind(self, portal, statement, params, parse_data):
1214 self.verifyState("ready")
1215 self._sock_lock.acquire()
1216 try:
1217 row_desc, param_fc = parse_data
1218 if row_desc == None:
1219
1220 output_fc = ()
1221 else:
1222
1223
1224 output_fc = [Types.py_type_info(f) for f in row_desc.fields]
1225 self._send(Protocol.Bind(portal, statement, param_fc, params, output_fc, self._client_encoding))
1226
1227
1228
1229 self._send(Protocol.DescribePortal(portal))
1230 self._send(Protocol.Flush())
1231 while 1:
1232 msg = self._read_message()
1233 if isinstance(msg, Protocol.BindComplete):
1234
1235 pass
1236 elif isinstance(msg, Protocol.NoData):
1237
1238 self._send(Protocol.Execute(portal, 0))
1239 self._send(Protocol.Sync())
1240 exc = None
1241 while 1:
1242 msg = self._read_message()
1243 if isinstance(msg, Protocol.CommandComplete):
1244
1245 pass
1246 elif isinstance(msg, Protocol.ReadyForQuery):
1247 if exc != None:
1248 raise exc
1249 break
1250 elif isinstance(msg, Protocol.ErrorResponse):
1251 exc = msg.createException()
1252 else:
1253 raise InternalError("unexpected response")
1254 return None
1255 elif isinstance(msg, Protocol.RowDescription):
1256
1257
1258 return msg
1259 elif isinstance(msg, Protocol.ErrorResponse):
1260 raise msg.createException()
1261 else:
1262 raise InternalError("Unexpected response msg %r" % (msg))
1263 finally:
1264 self._sock_lock.release()
1265
1266 - def fetch_rows(self, portal, row_count, row_desc):
1267 self.verifyState("ready")
1268 self._sock_lock.acquire()
1269 try:
1270 self._send(Protocol.Execute(portal, row_count))
1271 self._send(Protocol.Flush())
1272 rows = []
1273 end_of_data = False
1274 while 1:
1275 msg = self._read_message()
1276 if isinstance(msg, Protocol.DataRow):
1277 rows.append(
1278 [Types.py_value(msg.fields[i], row_desc.fields[i], client_encoding=self._client_encoding)
1279 for i in range(len(msg.fields))]
1280 )
1281 elif isinstance(msg, Protocol.PortalSuspended):
1282
1283 break
1284 elif isinstance(msg, Protocol.CommandComplete):
1285 self._send(Protocol.ClosePortal(portal))
1286 self._send(Protocol.Sync())
1287 while 1:
1288 msg = self._read_message()
1289 if isinstance(msg, Protocol.ReadyForQuery):
1290
1291 self._state = "ready"
1292 break
1293 elif isinstance(msg, Protocol.CloseComplete):
1294
1295 pass
1296 elif isinstance(msg, Protocol.ErrorResponse):
1297 raise msg.createException()
1298 else:
1299 raise InternalError("unexpected response msg %r" % msg)
1300 end_of_data = True
1301 break
1302 elif isinstance(msg, Protocol.ErrorResponse):
1303 raise msg.createException()
1304 else:
1305 raise InternalError("Unexpected response msg %r" % msg)
1306 return end_of_data, rows
1307 finally:
1308 self._sock_lock.release()
1309
1329
1349
1350 message_types = {
1351 "N": NoticeResponse,
1352 "R": AuthenticationRequest,
1353 "S": ParameterStatus,
1354 "K": BackendKeyData,
1355 "Z": ReadyForQuery,
1356 "T": RowDescription,
1357 "E": ErrorResponse,
1358 "D": DataRow,
1359 "C": CommandComplete,
1360 "1": ParseComplete,
1361 "2": BindComplete,
1362 "3": CloseComplete,
1363 "s": PortalSuspended,
1364 "n": NoData,
1365 "t": ParameterDescription,
1366 }
1367
1370
1372
1374 data = Types.py_types.get(typ)
1375 if data == None:
1376 raise NotSupportedError("type %r not mapped to pg type" % typ)
1377 type_oid = data.get("tid")
1378 if type_oid == None:
1379 raise InternalError("type %r has no type_oid" % typ)
1380 elif type_oid == -1:
1381
1382 return type_oid, 0
1383 prefer = data.get("prefer")
1384 if prefer != None:
1385 if prefer == "bin":
1386 if data.get("bin_out") == None:
1387 raise InternalError("bin format prefered but not avail for type %r" % typ)
1388 format = 1
1389 elif prefer == "txt":
1390 if data.get("txt_out") == None:
1391 raise InternalError("txt format prefered but not avail for type %r" % typ)
1392 format = 0
1393 else:
1394 raise InternalError("prefer flag not recognized for type %r" % typ)
1395 else:
1396
1397 if data.get("bin_out"):
1398 format = 1
1399 elif data.get("txt_out"):
1400 format = 0
1401 else:
1402 raise InternalError("no conversion fuction for type %r" % typ)
1403 return type_oid, format
1404 pg_type_info = staticmethod(pg_type_info)
1405
1407 typ = type(v)
1408 data = Types.py_types.get(typ)
1409 if data == None:
1410 raise NotSupportedError("type %r not mapped to pg type" % typ)
1411 elif data.get("tid") == -1:
1412
1413 return None
1414 if fc == 0:
1415 func = data.get("txt_out")
1416 elif fc == 1:
1417 func = data.get("bin_out")
1418 else:
1419 raise InternalError("unrecognized format code %r" % fc)
1420 if func == None:
1421 raise NotSupportedError("type %r, format code %r not supported" % (typ, fc))
1422 return func(v, **kwargs)
1423 pg_value = staticmethod(pg_value)
1424
1426 type_oid = description['type_oid']
1427 data = Types.pg_types.get(type_oid)
1428 if data == None:
1429 raise NotSupportedError("type oid %r not mapped to py type" % type_oid)
1430 prefer = data.get("prefer")
1431 if prefer != None:
1432 if prefer == "bin":
1433 if data.get("bin_in") == None:
1434 raise InternalError("bin format prefered but not avail for type oid %r" % type_oid)
1435 format = 1
1436 elif prefer == "txt":
1437 if data.get("txt_in") == None:
1438 raise InternalError("txt format prefered but not avail for type oid %r" % type_oid)
1439 format = 0
1440 else:
1441 raise InternalError("prefer flag not recognized for type oid %r" % type_oid)
1442 else:
1443
1444 if data.get("bin_in"):
1445 format = 1
1446 elif data.get("txt_in"):
1447 format = 0
1448 else:
1449 raise InternalError("no conversion fuction for type oid %r" % type_oid)
1450 return format
1451 py_type_info = staticmethod(py_type_info)
1452
1453 - def py_value(v, description, **kwargs):
1454 if v == None:
1455
1456 return None
1457 type_oid = description['type_oid']
1458 format = description['format']
1459 data = Types.pg_types.get(type_oid)
1460 if data == None:
1461 raise NotSupportedError("type oid %r not supported" % type_oid)
1462 if format == 0:
1463 func = data.get("txt_in")
1464 elif format == 1:
1465 func = data.get("bin_in")
1466 else:
1467 raise NotSupportedError("format code %r not supported" % format)
1468 if func == None:
1469 raise NotSupportedError("data response format %r, type %r not supported" % (format, type_oid))
1470 return func(v, **kwargs)
1471 py_value = staticmethod(py_value)
1472
1475
1477 return data == "\x01"
1478
1480 return struct.unpack("!h", data)[0]
1481
1484
1486 return struct.unpack("!i", data)[0]
1487
1490
1492 return struct.unpack("!q", data)[0]
1493
1496
1499
1501 return struct.unpack("!f", data)[0]
1502
1504 return struct.unpack("!d", data)[0]
1505
1508
1510 return struct.pack("!d", v)
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1522 year = int(data[0:4])
1523 month = int(data[5:7])
1524 day = int(data[8:10])
1525 hour = int(data[11:13])
1526 minute = int(data[14:16])
1527 sec = decimal.Decimal(data[17:])
1528 return datetime.datetime(year, month, day, hour, minute, int(sec), int((sec - int(sec)) * 1000000))
1529
1531 return v.isoformat(' ')
1532
1534 if data.find(".") == -1:
1535 return int(data)
1536 else:
1537 return decimal.Decimal(data)
1538
1541
1542 - def varcharin(data, client_encoding, **kwargs):
1543 return unicode(data, client_encoding)
1544
1545 - def textout(v, client_encoding, **kwargs):
1546 return v.encode(client_encoding)
1547
1549 year = int(data[0:4])
1550 month = int(data[5:7])
1551 day = int(data[8:10])
1552 hour = int(data[11:13])
1553 minute = int(data[14:16])
1554 tz_sep = data.rfind("-")
1555 sec = decimal.Decimal(data[17:tz_sep])
1556 tz = data[tz_sep:]
1557 print repr(data), repr(description)
1558 print repr(tz)
1559 return datetime.datetime(year, month, day, hour, minute, int(sec), int((sec - int(sec)) * 1000000), Types.FixedOffsetTz(tz))
1560
1563 self.hrs = int(hrs)
1564 self.name = hrs
1565
1567 return datetime.timedelta(hours=1) * self.hrs
1568
1571
1572 - def dst(self, dt):
1573 return datetime.timedelta(0)
1574
1577
1580
1581
1584
1585 py_types = {
1586 int: {"tid": 1700, "txt_out": numeric_out},
1587 long: {"tid": 1700, "txt_out": numeric_out},
1588 str: {"tid": 25, "txt_out": textout},
1589 unicode: {"tid": 25, "txt_out": textout},
1590 float: {"tid": 701, "bin_out": float8send},
1591 decimal.Decimal: {"tid": 1700, "txt_out": numeric_out},
1592 Bytea: {"tid": 17, "bin_out": byteasend},
1593 datetime.datetime: {"tid": 1114, "txt_out": timestamp_out},
1594 type(None): {"tid": -1},
1595 }
1596
1597 pg_types = {
1598 16: {"txt_in": boolin, "bin_in": boolrecv, "prefer": "bin"},
1599 17: {"bin_in": bytearecv},
1600 20: {"txt_in": int8in, "bin_in": int8recv, "prefer": "bin"},
1601 21: {"txt_in": int2in, "bin_in": int2recv, "prefer": "bin"},
1602 23: {"txt_in": int4in, "bin_in": int4recv, "prefer": "bin"},
1603 25: {"txt_in": varcharin},
1604 26: {"txt_in": numeric_in},
1605 700: {"txt_in": float4in, "bin_in": float4recv, "prefer": "bin"},
1606 701: {"txt_in": float8in, "bin_in": float8recv, "prefer": "bin"},
1607 1042: {"txt_in": varcharin},
1608 1043: {"txt_in": varcharin},
1609 1114: {"txt_in": timestamp_in},
1610 1186: {"txt_in": interval_in},
1611 1700: {"txt_in": numeric_in},
1612 }
1613
1614