| 85 | | ## |
|---|
| 86 | | # This class represents a connection to a PostgreSQL database. |
|---|
| 87 | | # <p> |
|---|
| 88 | | # A single PostgreSQL connection can only perform a single query at a time, |
|---|
| 89 | | # which is an important restriction to note. This limitation can be overcome |
|---|
| 90 | | # by retrieving all results immediately after a query, but this approach is not |
|---|
| 91 | | # taken by this library. |
|---|
| 92 | | # <p> |
|---|
| 93 | | # Stability: Added in v1.00, stability guaranteed for v1.xx. |
|---|
| 94 | | # |
|---|
| 95 | | # @param host The hostname of the PostgreSQL server to connect with. Only |
|---|
| 96 | | # TCP/IP connections are presently supported, so this parameter is mandatory. |
|---|
| 97 | | # |
|---|
| 98 | | # @param user The username to connect to the PostgreSQL server with. This |
|---|
| 99 | | # parameter is mandatory. |
|---|
| 100 | | # |
|---|
| 101 | | # @param port The TCP/IP port of the PostgreSQL server instance. This |
|---|
| 102 | | # parameter defaults to 5432, the registered and common port of PostgreSQL |
|---|
| 103 | | # TCP/IP servers. |
|---|
| 104 | | # |
|---|
| 105 | | # @param database The name of the database instance to connect with. This |
|---|
| 106 | | # parameter is optional, if omitted the PostgreSQL server will assume the |
|---|
| 107 | | # database name is the same as the username. |
|---|
| 108 | | # |
|---|
| 109 | | # @param password The user password to connect to the server with. This |
|---|
| 110 | | # parameter is optional. If omitted, and the database server requests password |
|---|
| 111 | | # based authentication, the connection will fail. On the other hand, if this |
|---|
| 112 | | # parameter is provided and the database does not request password |
|---|
| 113 | | # authentication, then the password will not be used. |
|---|
| 114 | | class Connection(object): |
|---|
| 115 | | |
|---|
| | 85 | class Cursor(object): |
|---|
| 127 | | try: |
|---|
| 128 | | self.c = Protocol.Connection(host, port) |
|---|
| 129 | | self.c.connect() |
|---|
| 130 | | self.c.authenticate(user, password=password, database=database) |
|---|
| 131 | | except socket.error, e: |
|---|
| 132 | | raise InterfaceError("communication error", e) |
|---|
| 133 | | |
|---|
| 134 | | def execute(self, command, *args): |
|---|
| 135 | | pass |
|---|
| 136 | | |
|---|
| 137 | | def query(self, query, *args): |
|---|
| 138 | | self._row_desc = self.c.extended_query('', '', query, args) |
|---|
| 139 | | #self._row_desc = self.c.query(query) |
|---|
| | 103 | self._cached_rows = [] |
|---|
| | 104 | self._command_complete = True |
|---|
| | 105 | |
|---|
| | 106 | def execute(self, query, *args): |
|---|
| | 107 | self._cached_rows = [] |
|---|
| | 108 | self._command_complete = False |
|---|
| | 109 | self._row_desc = self.c.extended_query(self.name, '', query, args) |
|---|
| | 160 | ## |
|---|
| | 161 | # This class represents a connection to a PostgreSQL database. |
|---|
| | 162 | # <p> |
|---|
| | 163 | # A single PostgreSQL connection can only perform a single query at a time, |
|---|
| | 164 | # which is an important restriction to note. This limitation can be overcome |
|---|
| | 165 | # by retrieving all results immediately after a query, but this approach is not |
|---|
| | 166 | # taken by this library. |
|---|
| | 167 | # <p> |
|---|
| | 168 | # Stability: Added in v1.00, stability guaranteed for v1.xx. |
|---|
| | 169 | # |
|---|
| | 170 | # @param host The hostname of the PostgreSQL server to connect with. Only |
|---|
| | 171 | # TCP/IP connections are presently supported, so this parameter is mandatory. |
|---|
| | 172 | # |
|---|
| | 173 | # @param user The username to connect to the PostgreSQL server with. This |
|---|
| | 174 | # parameter is mandatory. |
|---|
| | 175 | # |
|---|
| | 176 | # @param port The TCP/IP port of the PostgreSQL server instance. This |
|---|
| | 177 | # parameter defaults to 5432, the registered and common port of PostgreSQL |
|---|
| | 178 | # TCP/IP servers. |
|---|
| | 179 | # |
|---|
| | 180 | # @param database The name of the database instance to connect with. This |
|---|
| | 181 | # parameter is optional, if omitted the PostgreSQL server will assume the |
|---|
| | 182 | # database name is the same as the username. |
|---|
| | 183 | # |
|---|
| | 184 | # @param password The user password to connect to the server with. This |
|---|
| | 185 | # parameter is optional. If omitted, and the database server requests password |
|---|
| | 186 | # based authentication, the connection will fail. On the other hand, if this |
|---|
| | 187 | # parameter is provided and the database does not request password |
|---|
| | 188 | # authentication, then the password will not be used. |
|---|
| | 189 | class Connection(object): |
|---|
| | 190 | def __init__(self, host, user, port=5432, database=None, password=None): |
|---|
| | 191 | self._row_desc = None |
|---|
| | 192 | try: |
|---|
| | 193 | self.c = Protocol.Connection(host, port) |
|---|
| | 194 | self.c.connect() |
|---|
| | 195 | self.c.authenticate(user, password=password, database=database) |
|---|
| | 196 | except socket.error, e: |
|---|
| | 197 | raise InterfaceError("communication error", e) |
|---|
| | 198 | |
|---|
| | 281 | class Close(object): |
|---|
| | 282 | def __init__(self, typ, name): |
|---|
| | 283 | if len(typ) != 1: |
|---|
| | 284 | raise InternalError("Close typ must be 1 char") |
|---|
| | 285 | self.typ = typ |
|---|
| | 286 | self.name = name |
|---|
| | 287 | |
|---|
| | 288 | def serialize(self): |
|---|
| | 289 | val = self.typ + self.name + "\x00" |
|---|
| | 290 | val = struct.pack("!i", len(val) + 4) + val |
|---|
| | 291 | val = "C" + val |
|---|
| | 292 | return val |
|---|
| | 293 | |
|---|
| | 294 | class ClosePortal(Close): |
|---|
| | 295 | def __init__(self, name): |
|---|
| | 296 | Protocol.Close.__init__(self, "P", name) |
|---|
| | 297 | |
|---|
| | 298 | class ClosePreparedStatement(Close): |
|---|
| | 299 | def __init__(self, name): |
|---|
| | 300 | Protocol.Close.__init__(self, "S", name) |
|---|
| | 301 | |
|---|
| | 591 | def fetch_rows(self, portal, row_count): |
|---|
| | 592 | self.verifyState("ready") |
|---|
| | 593 | self._send(Protocol.Execute(portal, row_count)) |
|---|
| | 594 | self._send(Protocol.Flush()) |
|---|
| | 595 | rows = [] |
|---|
| | 596 | end_of_data = False |
|---|
| | 597 | while 1: |
|---|
| | 598 | msg = self._read_message() |
|---|
| | 599 | if isinstance(msg, Protocol.DataRow): |
|---|
| | 600 | rows.append(msg) |
|---|
| | 601 | elif isinstance(msg, Protocol.PortalSuspended): |
|---|
| | 602 | # got all the rows we asked for, but not all that exist |
|---|
| | 603 | break |
|---|
| | 604 | elif isinstance(msg, Protocol.CommandComplete): |
|---|
| | 605 | self._send(Protocol.ClosePortal(portal)) |
|---|
| | 606 | self._send(Protocol.Sync()) |
|---|
| | 607 | self._waitForReady() |
|---|
| | 608 | end_of_data = True |
|---|
| | 609 | break |
|---|
| | 610 | elif isinstance(msg, Protocol.ErrorResponse): |
|---|
| | 611 | raise msg.createException() |
|---|
| | 612 | else: |
|---|
| | 613 | raise InternalError("Unexpected response msg %r" % msg) |
|---|
| | 614 | return end_of_data, rows |
|---|
| | 615 | |
|---|