10
15
def connect(*args, **kwargs):
11
16
"""Connect to a database, returning a new Connection object."""
12
if libdrizzle is None:
13
libdrizzle = Drizzle()
14
connection = libdrizzle.create_client_connection(*args, **kwargs)
19
connection = _drizzle.create_client_connection(*args, **kwargs)
15
20
connection._connect()
19
return drizzle.drizzle_version()
24
return libdrizzle.drizzle_version()
26
def _columns_description(columns):
27
"""Given a list of libdrizzle Column objects, generate a list of
28
tuples suitable for the Python DB-API Cursor.descriptions field.
31
# TODO: preliminary code. Ensure that correct values are being returned here.
33
for column in columns:
34
# see http://bazaar.launchpad.net/~habnabit/oursql/master/annotate/head%3A/oursqlx/util.pyx#L26
36
column_type = column.column_type()
37
display_size = column.size()
38
internal_size = None # FIXME: bit length here
39
precision = None # FIXME: precision of float/decimal
40
scale = None # FIXME: column.decimals()?
41
null_ok = (column.flags() &
42
_libdrizzle.DRIZZLE_COLUMN_FLAGS_NOT_NULL) == 0
44
description.append((name, column_type, display_size, internal_size,
45
precision, scale, null_ok))
21
47
cdef class Drizzle:
23
cdef drizzle.drizzle_st * _st_drizzle
49
cdef libdrizzle.drizzle_st * _st_drizzle
24
50
def __cinit__(self, Drizzle fromdrizz= None):
25
51
if fromdrizz is None:
26
self._st_drizzle = drizzle.drizzle_create(NULL)
52
self._st_drizzle = libdrizzle.drizzle_create(NULL)
28
self._st_drizzle = drizzle.drizzle_clone(NULL, fromdrizz._st_drizzle)
54
self._st_drizzle = libdrizzle.drizzle_clone(NULL, fromdrizz._st_drizzle)
30
56
def __dealloc__(self):
31
cdef drizzle.drizzle_st *st_drizzle = self._st_drizzle
57
cdef libdrizzle.drizzle_st *st_drizzle = self._st_drizzle
32
58
if st_drizzle != NULL:
33
drizzle.drizzle_free(self._st_drizzle)
59
libdrizzle.drizzle_free(self._st_drizzle)
35
61
def create_client_connection(self, *args, **kwargs):
36
62
conn= Connection(self, *args, **kwargs)
56
82
def __dealloc__(self):
57
83
if self._st_conn != NULL:
58
drizzle.drizzle_con_free(self._st_conn)
84
libdrizzle.drizzle_con_free(self._st_conn)
60
86
def _connect(self):
61
87
if self._st_conn == NULL:
62
self._st_conn = drizzle.drizzle_con_create(self._st_drizzle._st_drizzle, NULL)
63
drizzle.drizzle_con_set_tcp(self._st_conn, self.host, self.port)
88
self._st_conn = libdrizzle.drizzle_con_create(self._st_drizzle._st_drizzle, NULL)
89
libdrizzle.drizzle_con_set_tcp(self._st_conn, self.host, self.port)
64
90
#self._st_conn.drizzle_con_set_auth(self.username, self.password)
65
drizzle.drizzle_con_set_db(self._st_conn, self.database)
66
drizzle.drizzle_con_connect(self._st_conn)
91
libdrizzle.drizzle_con_set_db(self._st_conn, self.database)
92
libdrizzle.drizzle_con_connect(self._st_conn)
69
95
if self._st_conn != NULL:
70
drizzle.drizzle_con_close(self._st_conn)
71
drizzle.drizzle_con_free(self._st_conn)
96
libdrizzle.drizzle_con_close(self._st_conn)
97
libdrizzle.drizzle_con_free(self._st_conn)
72
98
self._st_conn = NULL
76
101
"""Return true if the Connection is not open."""
77
return self._st_conn == NULL
80
# """Return a new Cursor object using the connection."""
103
return self._st_conn == NULL
106
"""Return a new Cursor object using the connection."""
109
def query(self, char *sql):
110
"""Execute a query"""
111
libdrizzle.drizzle_con_query(self._st_conn, sql);
116
cdef libdrizzle.drizzle_result_st *_last_result
117
def __init__(self, connection):
118
self._connection = connection
123
"""Iterate over query result rows one-by-one."""
124
return iter(self.fetchone, None)
127
"""The Connection object on which this cursor was created."""
129
return self._connection
131
property _drizzle_connection:
133
return self.connection._drizzle_connection
135
def _check_connected(self):
136
"""Raise a ProgrammingError if the Connection has been closed."""
137
if self.connection.is_closed:
138
raise errors.ProgrammingError("Connection closed")
141
# Note: the SWIG destructors should take care of freeing _last_result and _columns when we replace them.
142
self._last_result = NULL
144
self._has_rows_left = False
145
self._description = None
147
def execute(self, sql):
148
"""Execute a database operation, making the results accessible
152
self._check_connected()
156
cdef libdrizzle.drizzle_return_t d_ret
157
self._last_result = libdrizzle.drizzle_query(self._drizzle_connection._st_conn, sql[:-1], len(sql), &d_ret)
159
if d_ret == libdrizzle.DRIZZLE_RETURN_OK:
161
if self._last_result.column_count() != 0:
162
self._columns = [column for column in
163
iter(self._last_result.read_column, None)]
164
self._has_rows_left = True
165
self._description = _columns_description(self._columns)
167
raise errors.DatabaseError(libdrizzle.drizzle_result_error_code(self._last_result), libdrizzle.drizzle_con_error(self._drizzle_connection._st_conn))
170
"""Fetch the next row of a query result set, returning a single
171
sequence, or None when no more data is available.
174
self._check_connected()
176
if self._last_result is None:
177
raise ProgrammingError
179
if self._has_rows_left:
180
row = self._last_result.buffer_row()
182
row = tuple([from_db.convert(field, valuetype=descr[1])
183
for descr, field in izip(self.description, row)])
185
self._has_rows_left = False
189
def fetchmany(self, size=None):
190
"""Fetch the next set of rows of a query result, returning a
191
sequence of sequences (e.g. a list of tuples). An empty sequence
192
is returned when no more rows are available.
194
The number of rows to fetch per call is specified by the
195
parameter. If it is not given, the cursor's arraysize
196
determines the number of rows to be fetched.
200
size = self.arraysize
202
return list(islice(self, size))
205
"""Fetch all (remaining) rows of a query result, returning them
206
as a sequence of sequences (e.g. a list of tuples).
209
# TODO: test and compare buffer_all with the current buffer_row implementation.
214
"""The number of rows that the last .execute*() produced.
216
The attribute is -1 in case no .execute*() has been performed on
217
the cursor or the rowcount of the last operation is cannot be
220
Note: for Drizzle, the row count of a query cannot be determined
221
until all rows have been fetched.
224
if self._last_result is None or self._has_rows_left:
227
return self._last_result.row_count()
231
"""The current 0-based index of the cursor in the result set or
232
None if the index cannot be determined.
235
# row_current() seems to be 1-indexed
236
return self._last_result.row_current()-1
239
def description(self):
240
"""A list of tuples describing the columns in the current result
243
Tuples returned are of the form:
244
(name, type, display_size, internal_size, precision, scale, null_ok)
247
return self._description