Mercurial > p > mysql-python > mysqldb-2
annotate MySQLdb/connections.py @ 9:0e37ee00beb7 MySQLdb
Merge changes from 1.2 branch (r470:483): Mostly build-related.
author | adustman |
---|---|
date | Mon, 26 Feb 2007 00:55:29 +0000 |
parents | b70cce9bd065 |
children | 7773efbe9b30 |
rev | line source |
---|---|
0 | 1 """ |
2 | |
3 This module implements connections for MySQLdb. Presently there is | |
4 only one class: Connection. Others are unlikely. However, you might | |
5 want to make your own subclasses. In most cases, you will probably | |
6 override Connection.default_cursor with a non-standard Cursor class. | |
7 | |
8 """ | |
9 import cursors | |
10 from _mysql_exceptions import Warning, Error, InterfaceError, DataError, \ | |
11 DatabaseError, OperationalError, IntegrityError, InternalError, \ | |
12 NotSupportedError, ProgrammingError | |
13 import types, _mysql | |
14 | |
15 | |
16 def defaulterrorhandler(connection, cursor, errorclass, errorvalue): | |
17 """ | |
18 | |
19 If cursor is not None, (errorclass, errorvalue) is appended to | |
20 cursor.messages; otherwise it is appended to | |
21 connection.messages. Then errorclass is raised with errorvalue as | |
22 the value. | |
23 | |
24 You can override this with your own error handler by assigning it | |
25 to the instance. | |
26 | |
27 """ | |
28 error = errorclass, errorvalue | |
29 if cursor: | |
30 cursor.messages.append(error) | |
31 else: | |
32 connection.messages.append(error) | |
33 del cursor | |
34 del connection | |
35 raise errorclass, errorvalue | |
36 | |
37 | |
38 class Connection(_mysql.connection): | |
39 | |
40 """MySQL Database Connection Object""" | |
41 | |
42 default_cursor = cursors.Cursor | |
43 | |
44 def __init__(self, *args, **kwargs): | |
45 """ | |
46 | |
47 Create a connection to the database. It is strongly recommended | |
48 that you only use keyword parameters. Consult the MySQL C API | |
49 documentation for more information. | |
50 | |
51 host | |
52 string, host to connect | |
53 | |
54 user | |
55 string, user to connect as | |
56 | |
57 passwd | |
58 string, password to use | |
59 | |
60 db | |
61 string, database to use | |
62 | |
63 port | |
64 integer, TCP/IP port to connect to | |
65 | |
66 unix_socket | |
67 string, location of unix_socket to use | |
68 | |
69 conv | |
70 conversion dictionary, see MySQLdb.converters | |
71 | |
4 | 72 connect_timeout |
0 | 73 number of seconds to wait before the connection attempt |
74 fails. | |
75 | |
76 compress | |
77 if set, compression is enabled | |
78 | |
79 named_pipe | |
80 if set, a named pipe is used to connect (Windows only) | |
81 | |
82 init_command | |
83 command which is run once the connection is created | |
84 | |
85 read_default_file | |
86 file from which default client values are read | |
87 | |
88 read_default_group | |
89 configuration group to use from the default file | |
90 | |
91 cursorclass | |
92 class object, used to create cursors (keyword only) | |
93 | |
94 use_unicode | |
95 If True, text-like columns are returned as unicode objects | |
96 using the connection's character set. Otherwise, text-like | |
97 columns are returned as strings. columns are returned as | |
98 normal strings. Unicode objects will always be encoded to | |
99 the connection's character set regardless of this setting. | |
100 | |
101 charset | |
102 If supplied, the connection character set will be changed | |
103 to this character set (MySQL-4.1 and newer). This implies | |
104 use_unicode=True. | |
105 | |
106 sql_mode | |
107 If supplied, the session SQL mode will be changed to this | |
108 setting (MySQL-4.1 and newer). For more details and legal | |
109 values, see the MySQL documentation. | |
110 | |
111 client_flag | |
112 integer, flags to use or 0 | |
113 (see MySQL docs or constants/CLIENTS.py) | |
114 | |
115 ssl | |
116 dictionary or mapping, contains SSL connection parameters; | |
117 see the MySQL documentation for more details | |
118 (mysql_ssl_set()). If this is set, and the client does not | |
1 | 119 support SSL, NotSupportedError will be raised. |
0 | 120 |
121 local_infile | |
122 integer, non-zero enables LOAD LOCAL INFILE; zero disables | |
123 | |
124 There are a number of undocumented, non-standard methods. See the | |
125 documentation for the MySQL C API for some hints on what they do. | |
126 | |
127 """ | |
128 from constants import CLIENT, FIELD_TYPE | |
129 from converters import conversions | |
130 from weakref import proxy, WeakValueDictionary | |
131 | |
132 import types | |
133 | |
134 kwargs2 = kwargs.copy() | |
135 | |
136 if kwargs.has_key('conv'): | |
137 conv = kwargs['conv'] | |
138 else: | |
139 conv = conversions | |
140 | |
5 | 141 conv2 = {} |
142 for k, v in conv.items(): | |
143 if isinstance(k, int): | |
144 if isinstance(v, list): | |
145 conv2[k] = v[:] | |
146 else: | |
147 conv2[k] = v | |
148 kwargs2['conv'] = conv2 | |
149 | |
0 | 150 self.cursorclass = kwargs2.pop('cursorclass', self.default_cursor) |
151 charset = kwargs2.pop('charset', '') | |
152 | |
153 if charset: | |
154 use_unicode = True | |
155 else: | |
156 use_unicode = False | |
157 | |
158 use_unicode = kwargs2.pop('use_unicode', use_unicode) | |
159 sql_mode = kwargs2.pop('sql_mode', '') | |
160 | |
161 client_flag = kwargs.get('client_flag', 0) | |
162 client_version = tuple([ int(n) for n in _mysql.get_client_info().split('.')[:2] ]) | |
163 if client_version >= (4, 1): | |
164 client_flag |= CLIENT.MULTI_STATEMENTS | |
165 if client_version >= (5, 0): | |
166 client_flag |= CLIENT.MULTI_RESULTS | |
167 | |
168 kwargs2['client_flag'] = client_flag | |
169 | |
170 super(Connection, self).__init__(*args, **kwargs2) | |
171 | |
172 self.encoders = dict([ (k, v) for k, v in conv.items() | |
173 if type(k) is not int ]) | |
174 | |
175 self._server_version = tuple([ int(n) for n in self.get_server_info().split('.')[:2] ]) | |
176 | |
177 db = proxy(self) | |
178 def _get_string_literal(): | |
179 def string_literal(obj, dummy=None): | |
180 return db.string_literal(obj) | |
181 return string_literal | |
182 | |
183 def _get_unicode_literal(): | |
184 def unicode_literal(u, dummy=None): | |
185 return db.literal(u.encode(unicode_literal.charset)) | |
186 return unicode_literal | |
187 | |
188 def _get_string_decoder(): | |
189 def string_decoder(s): | |
190 return s.decode(string_decoder.charset) | |
191 return string_decoder | |
192 | |
193 string_literal = _get_string_literal() | |
194 self.unicode_literal = unicode_literal = _get_unicode_literal() | |
195 self.string_decoder = string_decoder = _get_string_decoder() | |
196 if not charset: | |
197 charset = self.character_set_name() | |
198 self.set_character_set(charset) | |
199 | |
200 if sql_mode: | |
201 self.set_sql_mode(sql_mode) | |
202 | |
203 if use_unicode: | |
4 | 204 self.converter[FIELD_TYPE.STRING].append((None, string_decoder)) |
205 self.converter[FIELD_TYPE.VAR_STRING].append((None, string_decoder)) | |
206 self.converter[FIELD_TYPE.VARCHAR].append((None, string_decoder)) | |
207 self.converter[FIELD_TYPE.BLOB].append((None, string_decoder)) | |
0 | 208 |
209 self.encoders[types.StringType] = string_literal | |
210 self.encoders[types.UnicodeType] = unicode_literal | |
211 self._transactional = self.server_capabilities & CLIENT.TRANSACTIONS | |
212 if self._transactional: | |
213 # PEP-249 requires autocommit to be initially off | |
214 self.autocommit(False) | |
215 self.messages = [] | |
216 | |
217 def cursor(self, cursorclass=None): | |
218 """ | |
219 | |
220 Create a cursor on which queries may be performed. The | |
221 optional cursorclass parameter is used to create the | |
222 Cursor. By default, self.cursorclass=cursors.Cursor is | |
223 used. | |
224 | |
225 """ | |
226 return (cursorclass or self.cursorclass)(self) | |
227 | |
9
0e37ee00beb7
Merge changes from 1.2 branch (r470:483): Mostly build-related.
adustman
parents:
5
diff
changeset
|
228 def __enter__(self): return self.cursor() |
0e37ee00beb7
Merge changes from 1.2 branch (r470:483): Mostly build-related.
adustman
parents:
5
diff
changeset
|
229 |
0e37ee00beb7
Merge changes from 1.2 branch (r470:483): Mostly build-related.
adustman
parents:
5
diff
changeset
|
230 def __exit__(self, exc, value, tb): |
0e37ee00beb7
Merge changes from 1.2 branch (r470:483): Mostly build-related.
adustman
parents:
5
diff
changeset
|
231 if exc: |
0e37ee00beb7
Merge changes from 1.2 branch (r470:483): Mostly build-related.
adustman
parents:
5
diff
changeset
|
232 self.rollback() |
0e37ee00beb7
Merge changes from 1.2 branch (r470:483): Mostly build-related.
adustman
parents:
5
diff
changeset
|
233 else: |
0e37ee00beb7
Merge changes from 1.2 branch (r470:483): Mostly build-related.
adustman
parents:
5
diff
changeset
|
234 self.commit() |
0e37ee00beb7
Merge changes from 1.2 branch (r470:483): Mostly build-related.
adustman
parents:
5
diff
changeset
|
235 |
0 | 236 def literal(self, o): |
237 """ | |
238 | |
239 If o is a single object, returns an SQL literal as a string. | |
240 If o is a non-string sequence, the items of the sequence are | |
241 converted and returned as a sequence. | |
242 | |
243 Non-standard. For internal use; do not use this in your | |
244 applications. | |
245 | |
246 """ | |
247 return self.escape(o, self.encoders) | |
248 | |
249 def begin(self): | |
250 """Explicitly begin a connection. Non-standard. | |
251 DEPRECATED: Will be removed in 1.3. | |
252 Use an SQL BEGIN statement instead.""" | |
253 from warnings import warn | |
254 warn("begin() is non-standard and will be removed in 1.3", | |
255 DeprecationWarning, 2) | |
256 self.query("BEGIN") | |
257 | |
258 if not hasattr(_mysql.connection, 'warning_count'): | |
259 | |
260 def warning_count(self): | |
261 """Return the number of warnings generated from the | |
262 last query. This is derived from the info() method.""" | |
263 from string import atoi | |
264 info = self.info() | |
265 if info: | |
266 return atoi(info.split()[-1]) | |
267 else: | |
268 return 0 | |
269 | |
270 def set_character_set(self, charset): | |
1 | 271 """Set the connection character set to charset. The character |
272 set can only be changed in MySQL-4.1 and newer. If you try | |
273 to change the character set from the current value in an | |
274 older version, NotSupportedError will be raised.""" | |
275 if self.character_set_name() != charset: | |
276 try: | |
277 super(Connection, self).set_character_set(charset) | |
278 except AttributeError: | |
279 if self._server_version < (4, 1): | |
280 raise NotSupportedError, "server is too old to set charset" | |
0 | 281 self.query('SET NAMES %s' % charset) |
282 self.store_result() | |
283 self.string_decoder.charset = charset | |
284 self.unicode_literal.charset = charset | |
285 | |
286 def set_sql_mode(self, sql_mode): | |
287 """Set the connection sql_mode. See MySQL documentation for | |
288 legal values.""" | |
289 if self._server_version < (4, 1): | |
1 | 290 raise NotSupportedError, "server is too old to set sql_mode" |
0 | 291 self.query("SET SESSION sql_mode='%s'" % sql_mode) |
292 self.store_result() | |
293 | |
294 def show_warnings(self): | |
295 """Return detailed information about warnings as a | |
296 sequence of tuples of (Level, Code, Message). This | |
297 is only supported in MySQL-4.1 and up. If your server | |
298 is an earlier version, an empty sequence is returned.""" | |
299 if self._server_version < (4,1): return () | |
300 self.query("SHOW WARNINGS") | |
301 r = self.store_result() | |
302 warnings = r.fetch_row(0) | |
303 return warnings | |
304 | |
305 Warning = Warning | |
306 Error = Error | |
307 InterfaceError = InterfaceError | |
308 DatabaseError = DatabaseError | |
309 DataError = DataError | |
310 OperationalError = OperationalError | |
311 IntegrityError = IntegrityError | |
312 InternalError = InternalError | |
313 ProgrammingError = ProgrammingError | |
314 NotSupportedError = NotSupportedError | |
315 | |
316 errorhandler = defaulterrorhandler |