/bangkokhotel/lib/python2.5/site-packages/django/db/backends/__init__.py
Python | 1012 lines | 881 code | 50 blank | 81 comment | 18 complexity | 4674c0e606646fe6ed3b96c7743ce6e6 MD5 | raw file
1from django.db.utils import DatabaseError
2
3try:
4 import thread
5except ImportError:
6 import dummy_thread as thread
7from contextlib import contextmanager
8
9from django.conf import settings
10from django.db import DEFAULT_DB_ALIAS
11from django.db.backends import util
12from django.db.transaction import TransactionManagementError
13from django.utils.importlib import import_module
14from django.utils.timezone import is_aware
15
16
17class BaseDatabaseWrapper(object):
18 """
19 Represents a database connection.
20 """
21 ops = None
22 vendor = 'unknown'
23
24 def __init__(self, settings_dict, alias=DEFAULT_DB_ALIAS,
25 allow_thread_sharing=False):
26 # `settings_dict` should be a dictionary containing keys such as
27 # NAME, USER, etc. It's called `settings_dict` instead of `settings`
28 # to disambiguate it from Django settings modules.
29 self.connection = None
30 self.queries = []
31 self.settings_dict = settings_dict
32 self.alias = alias
33 self.use_debug_cursor = None
34
35 # Transaction related attributes
36 self.transaction_state = []
37 self.savepoint_state = 0
38 self._dirty = None
39 self._thread_ident = thread.get_ident()
40 self.allow_thread_sharing = allow_thread_sharing
41
42 def __eq__(self, other):
43 return self.alias == other.alias
44
45 def __ne__(self, other):
46 return not self == other
47
48 def _commit(self):
49 if self.connection is not None:
50 return self.connection.commit()
51
52 def _rollback(self):
53 if self.connection is not None:
54 return self.connection.rollback()
55
56 def _enter_transaction_management(self, managed):
57 """
58 A hook for backend-specific changes required when entering manual
59 transaction handling.
60 """
61 pass
62
63 def _leave_transaction_management(self, managed):
64 """
65 A hook for backend-specific changes required when leaving manual
66 transaction handling. Will usually be implemented only when
67 _enter_transaction_management() is also required.
68 """
69 pass
70
71 def _savepoint(self, sid):
72 if not self.features.uses_savepoints:
73 return
74 self.cursor().execute(self.ops.savepoint_create_sql(sid))
75
76 def _savepoint_rollback(self, sid):
77 if not self.features.uses_savepoints:
78 return
79 self.cursor().execute(self.ops.savepoint_rollback_sql(sid))
80
81 def _savepoint_commit(self, sid):
82 if not self.features.uses_savepoints:
83 return
84 self.cursor().execute(self.ops.savepoint_commit_sql(sid))
85
86 def enter_transaction_management(self, managed=True):
87 """
88 Enters transaction management for a running thread. It must be balanced with
89 the appropriate leave_transaction_management call, since the actual state is
90 managed as a stack.
91
92 The state and dirty flag are carried over from the surrounding block or
93 from the settings, if there is no surrounding block (dirty is always false
94 when no current block is running).
95 """
96 if self.transaction_state:
97 self.transaction_state.append(self.transaction_state[-1])
98 else:
99 self.transaction_state.append(settings.TRANSACTIONS_MANAGED)
100
101 if self._dirty is None:
102 self._dirty = False
103 self._enter_transaction_management(managed)
104
105 def leave_transaction_management(self):
106 """
107 Leaves transaction management for a running thread. A dirty flag is carried
108 over to the surrounding block, as a commit will commit all changes, even
109 those from outside. (Commits are on connection level.)
110 """
111 self._leave_transaction_management(self.is_managed())
112 if self.transaction_state:
113 del self.transaction_state[-1]
114 else:
115 raise TransactionManagementError("This code isn't under transaction "
116 "management")
117 if self._dirty:
118 self.rollback()
119 raise TransactionManagementError("Transaction managed block ended with "
120 "pending COMMIT/ROLLBACK")
121 self._dirty = False
122
123 def validate_thread_sharing(self):
124 """
125 Validates that the connection isn't accessed by another thread than the
126 one which originally created it, unless the connection was explicitly
127 authorized to be shared between threads (via the `allow_thread_sharing`
128 property). Raises an exception if the validation fails.
129 """
130 if (not self.allow_thread_sharing
131 and self._thread_ident != thread.get_ident()):
132 raise DatabaseError("DatabaseWrapper objects created in a "
133 "thread can only be used in that same thread. The object "
134 "with alias '%s' was created in thread id %s and this is "
135 "thread id %s."
136 % (self.alias, self._thread_ident, thread.get_ident()))
137
138 def is_dirty(self):
139 """
140 Returns True if the current transaction requires a commit for changes to
141 happen.
142 """
143 return self._dirty
144
145 def set_dirty(self):
146 """
147 Sets a dirty flag for the current thread and code streak. This can be used
148 to decide in a managed block of code to decide whether there are open
149 changes waiting for commit.
150 """
151 if self._dirty is not None:
152 self._dirty = True
153 else:
154 raise TransactionManagementError("This code isn't under transaction "
155 "management")
156
157 def set_clean(self):
158 """
159 Resets a dirty flag for the current thread and code streak. This can be used
160 to decide in a managed block of code to decide whether a commit or rollback
161 should happen.
162 """
163 if self._dirty is not None:
164 self._dirty = False
165 else:
166 raise TransactionManagementError("This code isn't under transaction management")
167 self.clean_savepoints()
168
169 def clean_savepoints(self):
170 self.savepoint_state = 0
171
172 def is_managed(self):
173 """
174 Checks whether the transaction manager is in manual or in auto state.
175 """
176 if self.transaction_state:
177 return self.transaction_state[-1]
178 return settings.TRANSACTIONS_MANAGED
179
180 def managed(self, flag=True):
181 """
182 Puts the transaction manager into a manual state: managed transactions have
183 to be committed explicitly by the user. If you switch off transaction
184 management and there is a pending commit/rollback, the data will be
185 commited.
186 """
187 top = self.transaction_state
188 if top:
189 top[-1] = flag
190 if not flag and self.is_dirty():
191 self._commit()
192 self.set_clean()
193 else:
194 raise TransactionManagementError("This code isn't under transaction "
195 "management")
196
197 def commit_unless_managed(self):
198 """
199 Commits changes if the system is not in managed transaction mode.
200 """
201 self.validate_thread_sharing()
202 if not self.is_managed():
203 self._commit()
204 self.clean_savepoints()
205 else:
206 self.set_dirty()
207
208 def rollback_unless_managed(self):
209 """
210 Rolls back changes if the system is not in managed transaction mode.
211 """
212 self.validate_thread_sharing()
213 if not self.is_managed():
214 self._rollback()
215 else:
216 self.set_dirty()
217
218 def commit(self):
219 """
220 Does the commit itself and resets the dirty flag.
221 """
222 self.validate_thread_sharing()
223 self._commit()
224 self.set_clean()
225
226 def rollback(self):
227 """
228 This function does the rollback itself and resets the dirty flag.
229 """
230 self.validate_thread_sharing()
231 self._rollback()
232 self.set_clean()
233
234 def savepoint(self):
235 """
236 Creates a savepoint (if supported and required by the backend) inside the
237 current transaction. Returns an identifier for the savepoint that will be
238 used for the subsequent rollback or commit.
239 """
240 thread_ident = thread.get_ident()
241
242 self.savepoint_state += 1
243
244 tid = str(thread_ident).replace('-', '')
245 sid = "s%s_x%d" % (tid, self.savepoint_state)
246 self._savepoint(sid)
247 return sid
248
249 def savepoint_rollback(self, sid):
250 """
251 Rolls back the most recent savepoint (if one exists). Does nothing if
252 savepoints are not supported.
253 """
254 self.validate_thread_sharing()
255 if self.savepoint_state:
256 self._savepoint_rollback(sid)
257
258 def savepoint_commit(self, sid):
259 """
260 Commits the most recent savepoint (if one exists). Does nothing if
261 savepoints are not supported.
262 """
263 self.validate_thread_sharing()
264 if self.savepoint_state:
265 self._savepoint_commit(sid)
266
267 @contextmanager
268 def constraint_checks_disabled(self):
269 disabled = self.disable_constraint_checking()
270 try:
271 yield
272 finally:
273 if disabled:
274 self.enable_constraint_checking()
275
276 def disable_constraint_checking(self):
277 """
278 Backends can implement as needed to temporarily disable foreign key constraint
279 checking.
280 """
281 pass
282
283 def enable_constraint_checking(self):
284 """
285 Backends can implement as needed to re-enable foreign key constraint checking.
286 """
287 pass
288
289 def check_constraints(self, table_names=None):
290 """
291 Backends can override this method if they can apply constraint checking (e.g. via "SET CONSTRAINTS
292 ALL IMMEDIATE"). Should raise an IntegrityError if any invalid foreign key references are encountered.
293 """
294 pass
295
296 def close(self):
297 self.validate_thread_sharing()
298 if self.connection is not None:
299 self.connection.close()
300 self.connection = None
301
302 def cursor(self):
303 self.validate_thread_sharing()
304 if (self.use_debug_cursor or
305 (self.use_debug_cursor is None and settings.DEBUG)):
306 cursor = self.make_debug_cursor(self._cursor())
307 else:
308 cursor = util.CursorWrapper(self._cursor(), self)
309 return cursor
310
311 def make_debug_cursor(self, cursor):
312 return util.CursorDebugWrapper(cursor, self)
313
314class BaseDatabaseFeatures(object):
315 allows_group_by_pk = False
316 # True if django.db.backend.utils.typecast_timestamp is used on values
317 # returned from dates() calls.
318 needs_datetime_string_cast = True
319 empty_fetchmany_value = []
320 update_can_self_select = True
321
322 # Does the backend distinguish between '' and None?
323 interprets_empty_strings_as_nulls = False
324
325 # Does the backend allow inserting duplicate rows when a unique_together
326 # constraint exists, but one of the unique_together columns is NULL?
327 ignores_nulls_in_unique_constraints = True
328
329 can_use_chunked_reads = True
330 can_return_id_from_insert = False
331 has_bulk_insert = False
332 uses_autocommit = False
333 uses_savepoints = False
334 can_combine_inserts_with_and_without_auto_increment_pk = False
335
336 # If True, don't use integer foreign keys referring to, e.g., positive
337 # integer primary keys.
338 related_fields_match_type = False
339 allow_sliced_subqueries = True
340 has_select_for_update = False
341 has_select_for_update_nowait = False
342
343 supports_select_related = True
344
345 # Does the default test database allow multiple connections?
346 # Usually an indication that the test database is in-memory
347 test_db_allows_multiple_connections = True
348
349 # Can an object be saved without an explicit primary key?
350 supports_unspecified_pk = False
351
352 # Can a fixture contain forward references? i.e., are
353 # FK constraints checked at the end of transaction, or
354 # at the end of each save operation?
355 supports_forward_references = True
356
357 # Does a dirty transaction need to be rolled back
358 # before the cursor can be used again?
359 requires_rollback_on_dirty_transaction = False
360
361 # Does the backend allow very long model names without error?
362 supports_long_model_names = True
363
364 # Is there a REAL datatype in addition to floats/doubles?
365 has_real_datatype = False
366 supports_subqueries_in_group_by = True
367 supports_bitwise_or = True
368
369 # Do time/datetime fields have microsecond precision?
370 supports_microsecond_precision = True
371
372 # Does the __regex lookup support backreferencing and grouping?
373 supports_regex_backreferencing = True
374
375 # Can date/datetime lookups be performed using a string?
376 supports_date_lookup_using_string = True
377
378 # Can datetimes with timezones be used?
379 supports_timezones = True
380
381 # When performing a GROUP BY, is an ORDER BY NULL required
382 # to remove any ordering?
383 requires_explicit_null_ordering_when_grouping = False
384
385 # Is there a 1000 item limit on query parameters?
386 supports_1000_query_parameters = True
387
388 # Can an object have a primary key of 0? MySQL says No.
389 allows_primary_key_0 = True
390
391 # Do we need to NULL a ForeignKey out, or can the constraint check be
392 # deferred
393 can_defer_constraint_checks = False
394
395 # date_interval_sql can properly handle mixed Date/DateTime fields and timedeltas
396 supports_mixed_date_datetime_comparisons = True
397
398 # Does the backend support tablespaces? Default to False because it isn't
399 # in the SQL standard.
400 supports_tablespaces = False
401
402 # Features that need to be confirmed at runtime
403 # Cache whether the confirmation has been performed.
404 _confirmed = False
405 supports_transactions = None
406 supports_stddev = None
407 can_introspect_foreign_keys = None
408
409 # Support for the DISTINCT ON clause
410 can_distinct_on_fields = False
411
412 def __init__(self, connection):
413 self.connection = connection
414
415 def confirm(self):
416 "Perform manual checks of any database features that might vary between installs"
417 self._confirmed = True
418 self.supports_transactions = self._supports_transactions()
419 self.supports_stddev = self._supports_stddev()
420 self.can_introspect_foreign_keys = self._can_introspect_foreign_keys()
421
422 def _supports_transactions(self):
423 "Confirm support for transactions"
424 cursor = self.connection.cursor()
425 cursor.execute('CREATE TABLE ROLLBACK_TEST (X INT)')
426 self.connection._commit()
427 cursor.execute('INSERT INTO ROLLBACK_TEST (X) VALUES (8)')
428 self.connection._rollback()
429 cursor.execute('SELECT COUNT(X) FROM ROLLBACK_TEST')
430 count, = cursor.fetchone()
431 cursor.execute('DROP TABLE ROLLBACK_TEST')
432 self.connection._commit()
433 return count == 0
434
435 def _supports_stddev(self):
436 "Confirm support for STDDEV and related stats functions"
437 class StdDevPop(object):
438 sql_function = 'STDDEV_POP'
439
440 try:
441 self.connection.ops.check_aggregate_support(StdDevPop())
442 except NotImplementedError:
443 self.supports_stddev = False
444
445 def _can_introspect_foreign_keys(self):
446 "Confirm support for introspected foreign keys"
447 # Every database can do this reliably, except MySQL,
448 # which can't do it for MyISAM tables
449 return True
450
451
452class BaseDatabaseOperations(object):
453 """
454 This class encapsulates all backend-specific differences, such as the way
455 a backend performs ordering or calculates the ID of a recently-inserted
456 row.
457 """
458 compiler_module = "django.db.models.sql.compiler"
459
460 def __init__(self, connection):
461 self.connection = connection
462 self._cache = None
463
464 def autoinc_sql(self, table, column):
465 """
466 Returns any SQL needed to support auto-incrementing primary keys, or
467 None if no SQL is necessary.
468
469 This SQL is executed when a table is created.
470 """
471 return None
472
473 def bulk_batch_size(self, fields, objs):
474 """
475 Returns the maximum allowed batch size for the backend. The fields
476 are the fields going to be inserted in the batch, the objs contains
477 all the objects to be inserted.
478 """
479 return len(objs)
480
481 def date_extract_sql(self, lookup_type, field_name):
482 """
483 Given a lookup_type of 'year', 'month' or 'day', returns the SQL that
484 extracts a value from the given date field field_name.
485 """
486 raise NotImplementedError()
487
488 def date_interval_sql(self, sql, connector, timedelta):
489 """
490 Implements the date interval functionality for expressions
491 """
492 raise NotImplementedError()
493
494 def date_trunc_sql(self, lookup_type, field_name):
495 """
496 Given a lookup_type of 'year', 'month' or 'day', returns the SQL that
497 truncates the given date field field_name to a DATE object with only
498 the given specificity.
499 """
500 raise NotImplementedError()
501
502 def datetime_cast_sql(self):
503 """
504 Returns the SQL necessary to cast a datetime value so that it will be
505 retrieved as a Python datetime object instead of a string.
506
507 This SQL should include a '%s' in place of the field's name.
508 """
509 return "%s"
510
511 def deferrable_sql(self):
512 """
513 Returns the SQL necessary to make a constraint "initially deferred"
514 during a CREATE TABLE statement.
515 """
516 return ''
517
518 def distinct_sql(self, fields):
519 """
520 Returns an SQL DISTINCT clause which removes duplicate rows from the
521 result set. If any fields are given, only the given fields are being
522 checked for duplicates.
523 """
524 if fields:
525 raise NotImplementedError('DISTINCT ON fields is not supported by this database backend')
526 else:
527 return 'DISTINCT'
528
529 def drop_foreignkey_sql(self):
530 """
531 Returns the SQL command that drops a foreign key.
532 """
533 return "DROP CONSTRAINT"
534
535 def drop_sequence_sql(self, table):
536 """
537 Returns any SQL necessary to drop the sequence for the given table.
538 Returns None if no SQL is necessary.
539 """
540 return None
541
542 def fetch_returned_insert_id(self, cursor):
543 """
544 Given a cursor object that has just performed an INSERT...RETURNING
545 statement into a table that has an auto-incrementing ID, returns the
546 newly created ID.
547 """
548 return cursor.fetchone()[0]
549
550 def field_cast_sql(self, db_type):
551 """
552 Given a column type (e.g. 'BLOB', 'VARCHAR'), returns the SQL necessary
553 to cast it before using it in a WHERE statement. Note that the
554 resulting string should contain a '%s' placeholder for the column being
555 searched against.
556 """
557 return '%s'
558
559 def force_no_ordering(self):
560 """
561 Returns a list used in the "ORDER BY" clause to force no ordering at
562 all. Returning an empty list means that nothing will be included in the
563 ordering.
564 """
565 return []
566
567 def for_update_sql(self, nowait=False):
568 """
569 Returns the FOR UPDATE SQL clause to lock rows for an update operation.
570 """
571 if nowait:
572 return 'FOR UPDATE NOWAIT'
573 else:
574 return 'FOR UPDATE'
575
576 def fulltext_search_sql(self, field_name):
577 """
578 Returns the SQL WHERE clause to use in order to perform a full-text
579 search of the given field_name. Note that the resulting string should
580 contain a '%s' placeholder for the value being searched against.
581 """
582 raise NotImplementedError('Full-text search is not implemented for this database backend')
583
584 def last_executed_query(self, cursor, sql, params):
585 """
586 Returns a string of the query last executed by the given cursor, with
587 placeholders replaced with actual values.
588
589 `sql` is the raw query containing placeholders, and `params` is the
590 sequence of parameters. These are used by default, but this method
591 exists for database backends to provide a better implementation
592 according to their own quoting schemes.
593 """
594 from django.utils.encoding import smart_unicode, force_unicode
595
596 # Convert params to contain Unicode values.
597 to_unicode = lambda s: force_unicode(s, strings_only=True, errors='replace')
598 if isinstance(params, (list, tuple)):
599 u_params = tuple([to_unicode(val) for val in params])
600 else:
601 u_params = dict([(to_unicode(k), to_unicode(v)) for k, v in params.items()])
602
603 return smart_unicode(sql) % u_params
604
605 def last_insert_id(self, cursor, table_name, pk_name):
606 """
607 Given a cursor object that has just performed an INSERT statement into
608 a table that has an auto-incrementing ID, returns the newly created ID.
609
610 This method also receives the table name and the name of the primary-key
611 column.
612 """
613 return cursor.lastrowid
614
615 def lookup_cast(self, lookup_type):
616 """
617 Returns the string to use in a query when performing lookups
618 ("contains", "like", etc). The resulting string should contain a '%s'
619 placeholder for the column being searched against.
620 """
621 return "%s"
622
623 def max_in_list_size(self):
624 """
625 Returns the maximum number of items that can be passed in a single 'IN'
626 list condition, or None if the backend does not impose a limit.
627 """
628 return None
629
630 def max_name_length(self):
631 """
632 Returns the maximum length of table and column names, or None if there
633 is no limit.
634 """
635 return None
636
637 def no_limit_value(self):
638 """
639 Returns the value to use for the LIMIT when we are wanting "LIMIT
640 infinity". Returns None if the limit clause can be omitted in this case.
641 """
642 raise NotImplementedError
643
644 def pk_default_value(self):
645 """
646 Returns the value to use during an INSERT statement to specify that
647 the field should use its default value.
648 """
649 return 'DEFAULT'
650
651 def process_clob(self, value):
652 """
653 Returns the value of a CLOB column, for backends that return a locator
654 object that requires additional processing.
655 """
656 return value
657
658 def return_insert_id(self):
659 """
660 For backends that support returning the last insert ID as part
661 of an insert query, this method returns the SQL and params to
662 append to the INSERT query. The returned fragment should
663 contain a format string to hold the appropriate column.
664 """
665 pass
666
667 def compiler(self, compiler_name):
668 """
669 Returns the SQLCompiler class corresponding to the given name,
670 in the namespace corresponding to the `compiler_module` attribute
671 on this backend.
672 """
673 if self._cache is None:
674 self._cache = import_module(self.compiler_module)
675 return getattr(self._cache, compiler_name)
676
677 def quote_name(self, name):
678 """
679 Returns a quoted version of the given table, index or column name. Does
680 not quote the given name if it's already been quoted.
681 """
682 raise NotImplementedError()
683
684 def random_function_sql(self):
685 """
686 Returns a SQL expression that returns a random value.
687 """
688 return 'RANDOM()'
689
690 def regex_lookup(self, lookup_type):
691 """
692 Returns the string to use in a query when performing regular expression
693 lookups (using "regex" or "iregex"). The resulting string should
694 contain a '%s' placeholder for the column being searched against.
695
696 If the feature is not supported (or part of it is not supported), a
697 NotImplementedError exception can be raised.
698 """
699 raise NotImplementedError
700
701 def savepoint_create_sql(self, sid):
702 """
703 Returns the SQL for starting a new savepoint. Only required if the
704 "uses_savepoints" feature is True. The "sid" parameter is a string
705 for the savepoint id.
706 """
707 raise NotImplementedError
708
709 def savepoint_commit_sql(self, sid):
710 """
711 Returns the SQL for committing the given savepoint.
712 """
713 raise NotImplementedError
714
715 def savepoint_rollback_sql(self, sid):
716 """
717 Returns the SQL for rolling back the given savepoint.
718 """
719 raise NotImplementedError
720
721 def set_time_zone_sql(self):
722 """
723 Returns the SQL that will set the connection's time zone.
724
725 Returns '' if the backend doesn't support time zones.
726 """
727 return ''
728
729 def sql_flush(self, style, tables, sequences):
730 """
731 Returns a list of SQL statements required to remove all data from
732 the given database tables (without actually removing the tables
733 themselves).
734
735 The `style` argument is a Style object as returned by either
736 color_style() or no_style() in django.core.management.color.
737 """
738 raise NotImplementedError()
739
740 def sequence_reset_sql(self, style, model_list):
741 """
742 Returns a list of the SQL statements required to reset sequences for
743 the given models.
744
745 The `style` argument is a Style object as returned by either
746 color_style() or no_style() in django.core.management.color.
747 """
748 return [] # No sequence reset required by default.
749
750 def start_transaction_sql(self):
751 """
752 Returns the SQL statement required to start a transaction.
753 """
754 return "BEGIN;"
755
756 def end_transaction_sql(self, success=True):
757 if not success:
758 return "ROLLBACK;"
759 return "COMMIT;"
760
761 def tablespace_sql(self, tablespace, inline=False):
762 """
763 Returns the SQL that will be used in a query to define the tablespace.
764
765 Returns '' if the backend doesn't support tablespaces.
766
767 If inline is True, the SQL is appended to a row; otherwise it's appended
768 to the entire CREATE TABLE or CREATE INDEX statement.
769 """
770 return ''
771
772 def prep_for_like_query(self, x):
773 """Prepares a value for use in a LIKE query."""
774 from django.utils.encoding import smart_unicode
775 return smart_unicode(x).replace("\\", "\\\\").replace("%", "\%").replace("_", "\_")
776
777 # Same as prep_for_like_query(), but called for "iexact" matches, which
778 # need not necessarily be implemented using "LIKE" in the backend.
779 prep_for_iexact_query = prep_for_like_query
780
781 def value_to_db_date(self, value):
782 """
783 Transform a date value to an object compatible with what is expected
784 by the backend driver for date columns.
785 """
786 if value is None:
787 return None
788 return unicode(value)
789
790 def value_to_db_datetime(self, value):
791 """
792 Transform a datetime value to an object compatible with what is expected
793 by the backend driver for datetime columns.
794 """
795 if value is None:
796 return None
797 return unicode(value)
798
799 def value_to_db_time(self, value):
800 """
801 Transform a time value to an object compatible with what is expected
802 by the backend driver for time columns.
803 """
804 if value is None:
805 return None
806 if is_aware(value):
807 raise ValueError("Django does not support timezone-aware times.")
808 return unicode(value)
809
810 def value_to_db_decimal(self, value, max_digits, decimal_places):
811 """
812 Transform a decimal.Decimal value to an object compatible with what is
813 expected by the backend driver for decimal (numeric) columns.
814 """
815 if value is None:
816 return None
817 return util.format_number(value, max_digits, decimal_places)
818
819 def year_lookup_bounds(self, value):
820 """
821 Returns a two-elements list with the lower and upper bound to be used
822 with a BETWEEN operator to query a field value using a year lookup
823
824 `value` is an int, containing the looked-up year.
825 """
826 first = '%s-01-01 00:00:00'
827 second = '%s-12-31 23:59:59.999999'
828 return [first % value, second % value]
829
830 def year_lookup_bounds_for_date_field(self, value):
831 """
832 Returns a two-elements list with the lower and upper bound to be used
833 with a BETWEEN operator to query a DateField value using a year lookup
834
835 `value` is an int, containing the looked-up year.
836
837 By default, it just calls `self.year_lookup_bounds`. Some backends need
838 this hook because on their DB date fields can't be compared to values
839 which include a time part.
840 """
841 return self.year_lookup_bounds(value)
842
843 def convert_values(self, value, field):
844 """Coerce the value returned by the database backend into a consistent type that
845 is compatible with the field type.
846 """
847 internal_type = field.get_internal_type()
848 if internal_type == 'DecimalField':
849 return value
850 elif internal_type and internal_type.endswith('IntegerField') or internal_type == 'AutoField':
851 return int(value)
852 elif internal_type in ('DateField', 'DateTimeField', 'TimeField'):
853 return value
854 # No field, or the field isn't known to be a decimal or integer
855 # Default to a float
856 return float(value)
857
858 def check_aggregate_support(self, aggregate_func):
859 """Check that the backend supports the provided aggregate
860
861 This is used on specific backends to rule out known aggregates
862 that are known to have faulty implementations. If the named
863 aggregate function has a known problem, the backend should
864 raise NotImplementedError.
865 """
866 pass
867
868 def combine_expression(self, connector, sub_expressions):
869 """Combine a list of subexpressions into a single expression, using
870 the provided connecting operator. This is required because operators
871 can vary between backends (e.g., Oracle with %% and &) and between
872 subexpression types (e.g., date expressions)
873 """
874 conn = ' %s ' % connector
875 return conn.join(sub_expressions)
876
877class BaseDatabaseIntrospection(object):
878 """
879 This class encapsulates all backend-specific introspection utilities
880 """
881 data_types_reverse = {}
882
883 def __init__(self, connection):
884 self.connection = connection
885
886 def get_field_type(self, data_type, description):
887 """Hook for a database backend to use the cursor description to
888 match a Django field type to a database column.
889
890 For Oracle, the column data_type on its own is insufficient to
891 distinguish between a FloatField and IntegerField, for example."""
892 return self.data_types_reverse[data_type]
893
894 def table_name_converter(self, name):
895 """Apply a conversion to the name for the purposes of comparison.
896
897 The default table name converter is for case sensitive comparison.
898 """
899 return name
900
901 def table_names(self):
902 "Returns a list of names of all tables that exist in the database."
903 cursor = self.connection.cursor()
904 return self.get_table_list(cursor)
905
906 def django_table_names(self, only_existing=False):
907 """
908 Returns a list of all table names that have associated Django models and
909 are in INSTALLED_APPS.
910
911 If only_existing is True, the resulting list will only include the tables
912 that actually exist in the database.
913 """
914 from django.db import models, router
915 tables = set()
916 for app in models.get_apps():
917 for model in models.get_models(app):
918 if not model._meta.managed:
919 continue
920 if not router.allow_syncdb(self.connection.alias, model):
921 continue
922 tables.add(model._meta.db_table)
923 tables.update([f.m2m_db_table() for f in model._meta.local_many_to_many])
924 tables = list(tables)
925 if only_existing:
926 existing_tables = self.table_names()
927 tables = [
928 t
929 for t in tables
930 if self.table_name_converter(t) in existing_tables
931 ]
932 return tables
933
934 def installed_models(self, tables):
935 "Returns a set of all models represented by the provided list of table names."
936 from django.db import models, router
937 all_models = []
938 for app in models.get_apps():
939 for model in models.get_models(app):
940 if router.allow_syncdb(self.connection.alias, model):
941 all_models.append(model)
942 tables = map(self.table_name_converter, tables)
943 return set([
944 m for m in all_models
945 if self.table_name_converter(m._meta.db_table) in tables
946 ])
947
948 def sequence_list(self):
949 "Returns a list of information about all DB sequences for all models in all apps."
950 from django.db import models, router
951
952 apps = models.get_apps()
953 sequence_list = []
954
955 for app in apps:
956 for model in models.get_models(app):
957 if not model._meta.managed:
958 continue
959 if not router.allow_syncdb(self.connection.alias, model):
960 continue
961 for f in model._meta.local_fields:
962 if isinstance(f, models.AutoField):
963 sequence_list.append({'table': model._meta.db_table, 'column': f.column})
964 break # Only one AutoField is allowed per model, so don't bother continuing.
965
966 for f in model._meta.local_many_to_many:
967 # If this is an m2m using an intermediate table,
968 # we don't need to reset the sequence.
969 if f.rel.through is None:
970 sequence_list.append({'table': f.m2m_db_table(), 'column': None})
971
972 return sequence_list
973
974 def get_key_columns(self, cursor, table_name):
975 """
976 Backends can override this to return a list of (column_name, referenced_table_name,
977 referenced_column_name) for all key columns in given table.
978 """
979 raise NotImplementedError
980
981 def get_primary_key_column(self, cursor, table_name):
982 """
983 Backends can override this to return the column name of the primary key for the given table.
984 """
985 raise NotImplementedError
986
987class BaseDatabaseClient(object):
988 """
989 This class encapsulates all backend-specific methods for opening a
990 client shell.
991 """
992 # This should be a string representing the name of the executable
993 # (e.g., "psql"). Subclasses must override this.
994 executable_name = None
995
996 def __init__(self, connection):
997 # connection is an instance of BaseDatabaseWrapper.
998 self.connection = connection
999
1000 def runshell(self):
1001 raise NotImplementedError()
1002
1003class BaseDatabaseValidation(object):
1004 """
1005 This class encapsualtes all backend-specific model validation.
1006 """
1007 def __init__(self, connection):
1008 self.connection = connection
1009
1010 def validate_field(self, errors, opts, f):
1011 "By default, there is no backend-specific validation"
1012 pass