Django

Code

root/django/trunk/django/db/backends/__init__.py

Revision 9004, 15.7 kB (checked in by ikelly, 2 months ago)

Fixed an incorrectly named DatabaseOperations? method. It was causing non-Oracle backends to fail when running syncdb with tablespaces set.

  • Property svn:eol-style set to native
Line 
1 try:
2     # Only exists in Python 2.4+
3     from threading import local
4 except ImportError:
5     # Import copy of _thread_local.py from Python 2.4
6     from django.utils._threading_local import local
7 try:
8     set
9 except NameError:
10     # Python 2.3 compat
11     from sets import Set as set
12
13 from django.db.backends import util
14 from django.utils import datetime_safe
15
16 class BaseDatabaseWrapper(local):
17     """
18     Represents a database connection.
19     """
20     ops = None
21     def __init__(self, **kwargs):
22         self.connection = None
23         self.queries = []
24         self.options = kwargs
25
26     def _commit(self):
27         if self.connection is not None:
28             return self.connection.commit()
29
30     def _rollback(self):
31         if self.connection is not None:
32             return self.connection.rollback()
33
34     def _savepoint(self, sid):
35         if not self.features.uses_savepoints:
36             return
37         self.connection.cursor().execute(self.ops.savepoint_create_sql(sid))
38
39     def _savepoint_rollback(self, sid):
40         if not self.features.uses_savepoints:
41             return
42         self.connection.cursor().execute(self.ops.savepoint_rollback_sql(sid))
43
44     def _savepoint_commit(self, sid):
45         if not self.features.uses_savepoints:
46             return
47         self.connection.cursor().execute(self.ops.savepoint_commit_sql(sid))
48
49     def close(self):
50         if self.connection is not None:
51             self.connection.close()
52             self.connection = None
53
54     def cursor(self):
55         from django.conf import settings
56         cursor = self._cursor(settings)
57         if settings.DEBUG:
58             return self.make_debug_cursor(cursor)
59         return cursor
60
61     def make_debug_cursor(self, cursor):
62         return util.CursorDebugWrapper(cursor, self)
63
64 class BaseDatabaseFeatures(object):
65     # True if django.db.backend.utils.typecast_timestamp is used on values
66     # returned from dates() calls.
67     needs_datetime_string_cast = True
68     uses_custom_query_class = False
69     empty_fetchmany_value = []
70     update_can_self_select = True
71     interprets_empty_strings_as_nulls = False
72     can_use_chunked_reads = True
73     uses_savepoints = False
74     # If True, don't use integer foreign keys referring to, e.g., positive
75     # integer primary keys.
76     related_fields_match_type = False
77
78 class BaseDatabaseOperations(object):
79     """
80     This class encapsulates all backend-specific differences, such as the way
81     a backend performs ordering or calculates the ID of a recently-inserted
82     row.
83     """
84     def autoinc_sql(self, table, column):
85         """
86         Returns any SQL needed to support auto-incrementing primary keys, or
87         None if no SQL is necessary.
88
89         This SQL is executed when a table is created.
90         """
91         return None
92
93     def date_extract_sql(self, lookup_type, field_name):
94         """
95         Given a lookup_type of 'year', 'month' or 'day', returns the SQL that
96         extracts a value from the given date field field_name.
97         """
98         raise NotImplementedError()
99
100     def date_trunc_sql(self, lookup_type, field_name):
101         """
102         Given a lookup_type of 'year', 'month' or 'day', returns the SQL that
103         truncates the given date field field_name to a DATE object with only
104         the given specificity.
105         """
106         raise NotImplementedError()
107
108     def datetime_cast_sql(self):
109         """
110         Returns the SQL necessary to cast a datetime value so that it will be
111         retrieved as a Python datetime object instead of a string.
112
113         This SQL should include a '%s' in place of the field's name.
114         """
115         return "%s"
116
117     def deferrable_sql(self):
118         """
119         Returns the SQL necessary to make a constraint "initially deferred"
120         during a CREATE TABLE statement.
121         """
122         return ''
123
124     def drop_foreignkey_sql(self):
125         """
126         Returns the SQL command that drops a foreign key.
127         """
128         return "DROP CONSTRAINT"
129
130     def drop_sequence_sql(self, table):
131         """
132         Returns any SQL necessary to drop the sequence for the given table.
133         Returns None if no SQL is necessary.
134         """
135         return None
136
137     def field_cast_sql(self, db_type):
138         """
139         Given a column type (e.g. 'BLOB', 'VARCHAR'), returns the SQL necessary
140         to cast it before using it in a WHERE statement. Note that the
141         resulting string should contain a '%s' placeholder for the column being
142         searched against.
143         """
144         return '%s'
145
146     def fulltext_search_sql(self, field_name):
147         """
148         Returns the SQL WHERE clause to use in order to perform a full-text
149         search of the given field_name. Note that the resulting string should
150         contain a '%s' placeholder for the value being searched against.
151         """
152         raise NotImplementedError('Full-text search is not implemented for this database backend')
153
154     def last_executed_query(self, cursor, sql, params):
155         """
156         Returns a string of the query last executed by the given cursor, with
157         placeholders replaced with actual values.
158
159         `sql` is the raw query containing placeholders, and `params` is the
160         sequence of parameters. These are used by default, but this method
161         exists for database backends to provide a better implementation
162         according to their own quoting schemes.
163         """
164         from django.utils.encoding import smart_unicode, force_unicode
165
166         # Convert params to contain Unicode values.
167         to_unicode = lambda s: force_unicode(s, strings_only=True)
168         if isinstance(params, (list, tuple)):
169             u_params = tuple([to_unicode(val) for val in params])
170         else:
171             u_params = dict([(to_unicode(k), to_unicode(v)) for k, v in params.items()])
172
173         return smart_unicode(sql) % u_params
174
175     def last_insert_id(self, cursor, table_name, pk_name):
176         """
177         Given a cursor object that has just performed an INSERT statement into
178         a table that has an auto-incrementing ID, returns the newly created ID.
179
180         This method also receives the table name and the name of the primary-key
181         column.
182         """
183         return cursor.lastrowid
184
185     def lookup_cast(self, lookup_type):
186         """
187         Returns the string to use in a query when performing lookups
188         ("contains", "like", etc). The resulting string should contain a '%s'
189         placeholder for the column being searched against.
190         """
191         return "%s"
192
193     def max_name_length(self):
194         """
195         Returns the maximum length of table and column names, or None if there
196         is no limit.
197         """
198         return None
199
200     def no_limit_value(self):
201         """
202         Returns the value to use for the LIMIT when we are wanting "LIMIT
203         infinity". Returns None if the limit clause can be omitted in this case.
204         """
205         # FIXME: API may need to change once Oracle backend is repaired.
206         raise NotImplementedError()
207
208     def pk_default_value(self):
209         """
210         Returns the value to use during an INSERT statement to specify that
211         the field should use its default value.
212         """
213         return 'DEFAULT'
214
215     def query_class(self, DefaultQueryClass):
216         """
217         Given the default Query class, returns a custom Query class
218         to use for this backend. Returns None if a custom Query isn't used.
219         See also BaseDatabaseFeatures.uses_custom_query_class, which regulates
220         whether this method is called at all.
221         """
222         return None
223
224     def quote_name(self, name):
225         """
226         Returns a quoted version of the given table, index or column name. Does
227         not quote the given name if it's already been quoted.
228         """
229         raise NotImplementedError()
230
231     def random_function_sql(self):
232         """
233         Returns a SQL expression that returns a random value.
234         """
235         return 'RANDOM()'
236
237     def regex_lookup(self, lookup_type):
238         """
239         Returns the string to use in a query when performing regular expression
240         lookups (using "regex" or "iregex"). The resulting string should
241         contain a '%s' placeholder for the column being searched against.
242
243         If the feature is not supported (or part of it is not supported), a
244         NotImplementedError exception can be raised.
245         """
246         raise NotImplementedError
247
248     def savepoint_create_sql(self, sid):
249         """
250         Returns the SQL for starting a new savepoint. Only required if the
251         "uses_savepoints" feature is True. The "sid" parameter is a string
252         for the savepoint id.
253         """
254         raise NotImplementedError
255
256     def savepoint_commit_sql(self, sid):
257         """
258         Returns the SQL for committing the given savepoint.
259         """
260         raise NotImplementedError
261
262     def savepoint_rollback_sql(self, sid):
263         """
264         Returns the SQL for rolling back the given savepoint.
265         """
266         raise NotImplementedError
267
268     def sql_flush(self, style, tables, sequences):
269         """
270         Returns a list of SQL statements required to remove all data from
271         the given database tables (without actually removing the tables
272         themselves).
273
274         The `style` argument is a Style object as returned by either
275         color_style() or no_style() in django.core.management.color.
276         """
277         raise NotImplementedError()
278
279     def sequence_reset_sql(self, style, model_list):
280         """
281         Returns a list of the SQL statements required to reset sequences for
282         the given models.
283
284         The `style` argument is a Style object as returned by either
285         color_style() or no_style() in django.core.management.color.
286         """
287         return [] # No sequence reset required by default.
288
289     def start_transaction_sql(self):
290         """
291         Returns the SQL statement required to start a transaction.
292         """
293         return "BEGIN;"
294
295     def tablespace_sql(self, tablespace, inline=False):
296         """
297         Returns the SQL that will be appended to tables or rows to define
298         a tablespace. Returns '' if the backend doesn't use tablespaces.
299         """
300         return ''
301
302     def prep_for_like_query(self, x):
303         """Prepares a value for use in a LIKE query."""
304         from django.utils.encoding import smart_unicode
305         return smart_unicode(x).replace("\\", "\\\\").replace("%", "\%").replace("_", "\_")
306
307     # Same as prep_for_like_query(), but called for "iexact" matches, which
308     # need not necessarily be implemented using "LIKE" in the backend.
309     prep_for_iexact_query = prep_for_like_query
310
311     def value_to_db_date(self, value):
312         """
313         Transform a date value to an object compatible with what is expected
314         by the backend driver for date columns.
315         """
316         if value is None:
317             return None
318         return datetime_safe.new_date(value).strftime('%Y-%m-%d')
319
320     def value_to_db_datetime(self, value):
321         """
322         Transform a datetime value to an object compatible with what is expected
323         by the backend driver for datetime columns.
324         """
325         if value is None:
326             return None
327         return unicode(value)
328
329     def value_to_db_time(self, value):
330         """
331         Transform a datetime value to an object compatible with what is expected
332         by the backend driver for time columns.
333         """
334         if value is None:
335             return None
336         return unicode(value)
337
338     def value_to_db_decimal(self, value, max_digits, decimal_places):
339         """
340         Transform a decimal.Decimal value to an object compatible with what is
341         expected by the backend driver for decimal (numeric) columns.
342         """
343         if value is None:
344             return None
345         return util.format_number(value, max_digits, decimal_places)
346
347     def year_lookup_bounds(self, value):
348         """
349         Returns a two-elements list with the lower and upper bound to be used
350         with a BETWEEN operator to query a field value using a year lookup
351
352         `value` is an int, containing the looked-up year.
353         """
354         first = '%s-01-01 00:00:00'
355         second = '%s-12-31 23:59:59.999999'
356         return [first % value, second % value]
357
358     def year_lookup_bounds_for_date_field(self, value):
359         """
360         Returns a two-elements list with the lower and upper bound to be used
361         with a BETWEEN operator to query a DateField value using a year lookup
362
363         `value` is an int, containing the looked-up year.
364
365         By default, it just calls `self.year_lookup_bounds`. Some backends need
366         this hook because on their DB date fields can't be compared to values
367         which include a time part.
368         """
369         return self.year_lookup_bounds(value)
370
371 class BaseDatabaseIntrospection(object):
372     """
373     This class encapsulates all backend-specific introspection utilities
374     """
375     data_types_reverse = {}
376
377     def __init__(self, connection):
378         self.connection = connection
379
380     def table_name_converter(self, name):
381         """Apply a conversion to the name for the purposes of comparison.
382
383         The default table name converter is for case sensitive comparison.
384         """
385         return name
386
387     def table_names(self):
388         "Returns a list of names of all tables that exist in the database."
389         cursor = self.connection.cursor()
390         return self.get_table_list(cursor)
391
392     def django_table_names(self, only_existing=False):
393         """
394         Returns a list of all table names that have associated Django models and
395         are in INSTALLED_APPS.
396
397         If only_existing is True, the resulting list will only include the tables
398         that actually exist in the database.
399         """
400         from django.db import models
401         tables = set()
402         for app in models.get_apps():
403             for model in models.get_models(app):
404                 tables.add(model._meta.db_table)
405                 tables.update([f.m2m_db_table() for f in model._meta.local_many_to_many])
406         if only_existing:
407             tables = [t for t in tables if t in self.table_names()]
408         return tables
409
410     def installed_models(self, tables):
411         "Returns a set of all models represented by the provided list of table names."
412         from django.db import models
413         all_models = []
414         for app in models.get_apps():
415             for model in models.get_models(app):
416                 all_models.append(model)
417         return set([m for m in all_models
418             if self.table_name_converter(m._meta.db_table) in map(self.table_name_converter, tables)
419         ])
420
421     def sequence_list(self):
422         "Returns a list of information about all DB sequences for all models in all apps."
423         from django.db import models
424
425         apps = models.get_apps()
426         sequence_list = []
427
428         for app in apps:
429             for model in models.get_models(app):
430                 for f in model._meta.local_fields:
431                     if isinstance(f, models.AutoField):
432                         sequence_list.append({'table': model._meta.db_table, 'column': f.column})
433                         break # Only one AutoField is allowed per model, so don't bother continuing.
434
435                 for f in model._meta.local_many_to_many:
436                     sequence_list.append({'table': f.m2m_db_table(), 'column': None})
437
438         return sequence_list
439
440 class BaseDatabaseClient(object):
441     """
442     This class encapsulates all backend-specific methods for opening a
443     client shell.
444     """
445     # This should be a string representing the name of the executable
446     # (e.g., "psql"). Subclasses must override this.
447     executable_name = None
448
449     def runshell(self):
450         raise NotImplementedError()
451
452 class BaseDatabaseValidation(object):
453     """
454     This class encapsualtes all backend-specific model validation.
455     """
456     def validate_field(self, errors, opts, f):
457         "By default, there is no backend-specific validation"
458         pass
Note: See TracBrowser for help on using the browser.