web/lib/django/db/backends/__init__.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
     1 try:
     1 import decimal
     2     # Only exists in Python 2.4+
     2 from threading import local
     3     from threading import local
     3 
     4 except ImportError:
     4 from django.db import DEFAULT_DB_ALIAS
     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 try:
       
    14     import decimal
       
    15 except ImportError:
       
    16     # Python 2.3 fallback
       
    17     from django.utils import _decimal as decimal
       
    18 
       
    19 from django.db.backends import util
     5 from django.db.backends import util
    20 from django.utils import datetime_safe
     6 from django.utils import datetime_safe
       
     7 from django.utils.importlib import import_module
    21 
     8 
    22 class BaseDatabaseWrapper(local):
     9 class BaseDatabaseWrapper(local):
    23     """
    10     """
    24     Represents a database connection.
    11     Represents a database connection.
    25     """
    12     """
    26     ops = None
    13     ops = None
    27     def __init__(self, settings_dict):
    14 
       
    15     def __init__(self, settings_dict, alias=DEFAULT_DB_ALIAS):
    28         # `settings_dict` should be a dictionary containing keys such as
    16         # `settings_dict` should be a dictionary containing keys such as
    29         # DATABASE_NAME, DATABASE_USER, etc. It's called `settings_dict`
    17         # NAME, USER, etc. It's called `settings_dict` instead of `settings`
    30         # instead of `settings` to disambiguate it from Django settings
    18         # to disambiguate it from Django settings modules.
    31         # modules.
       
    32         self.connection = None
    19         self.connection = None
    33         self.queries = []
    20         self.queries = []
    34         self.settings_dict = settings_dict
    21         self.settings_dict = settings_dict
       
    22         self.alias = alias
       
    23 
       
    24     def __eq__(self, other):
       
    25         return self.settings_dict == other.settings_dict
       
    26 
       
    27     def __ne__(self, other):
       
    28         return not self == other
    35 
    29 
    36     def _commit(self):
    30     def _commit(self):
    37         if self.connection is not None:
    31         if self.connection is not None:
    38             return self.connection.commit()
    32             return self.connection.commit()
    39 
    33 
    89 class BaseDatabaseFeatures(object):
    83 class BaseDatabaseFeatures(object):
    90     allows_group_by_pk = False
    84     allows_group_by_pk = False
    91     # True if django.db.backend.utils.typecast_timestamp is used on values
    85     # True if django.db.backend.utils.typecast_timestamp is used on values
    92     # returned from dates() calls.
    86     # returned from dates() calls.
    93     needs_datetime_string_cast = True
    87     needs_datetime_string_cast = True
    94     uses_custom_query_class = False
       
    95     empty_fetchmany_value = []
    88     empty_fetchmany_value = []
    96     update_can_self_select = True
    89     update_can_self_select = True
    97     interprets_empty_strings_as_nulls = False
    90     interprets_empty_strings_as_nulls = False
    98     can_use_chunked_reads = True
    91     can_use_chunked_reads = True
    99     can_return_id_from_insert = False
    92     can_return_id_from_insert = False
   100     uses_autocommit = False
    93     uses_autocommit = False
   101     uses_savepoints = False
    94     uses_savepoints = False
   102     # If True, don't use integer foreign keys referring to, e.g., positive
    95     # If True, don't use integer foreign keys referring to, e.g., positive
   103     # integer primary keys.
    96     # integer primary keys.
   104     related_fields_match_type = False
    97     related_fields_match_type = False
       
    98     allow_sliced_subqueries = True
   105 
    99 
   106 class BaseDatabaseOperations(object):
   100 class BaseDatabaseOperations(object):
   107     """
   101     """
   108     This class encapsulates all backend-specific differences, such as the way
   102     This class encapsulates all backend-specific differences, such as the way
   109     a backend performs ordering or calculates the ID of a recently-inserted
   103     a backend performs ordering or calculates the ID of a recently-inserted
   110     row.
   104     row.
   111     """
   105     """
       
   106     compiler_module = "django.db.models.sql.compiler"
       
   107 
       
   108     def __init__(self):
       
   109         self._cache = {}
       
   110 
   112     def autoinc_sql(self, table, column):
   111     def autoinc_sql(self, table, column):
   113         """
   112         """
   114         Returns any SQL needed to support auto-incrementing primary keys, or
   113         Returns any SQL needed to support auto-incrementing primary keys, or
   115         None if no SQL is necessary.
   114         None if no SQL is necessary.
   116 
   115 
   206         according to their own quoting schemes.
   205         according to their own quoting schemes.
   207         """
   206         """
   208         from django.utils.encoding import smart_unicode, force_unicode
   207         from django.utils.encoding import smart_unicode, force_unicode
   209 
   208 
   210         # Convert params to contain Unicode values.
   209         # Convert params to contain Unicode values.
   211         to_unicode = lambda s: force_unicode(s, strings_only=True)
   210         to_unicode = lambda s: force_unicode(s, strings_only=True, errors='replace')
   212         if isinstance(params, (list, tuple)):
   211         if isinstance(params, (list, tuple)):
   213             u_params = tuple([to_unicode(val) for val in params])
   212             u_params = tuple([to_unicode(val) for val in params])
   214         else:
   213         else:
   215             u_params = dict([(to_unicode(k), to_unicode(v)) for k, v in params.items()])
   214             u_params = dict([(to_unicode(k), to_unicode(v)) for k, v in params.items()])
   216 
   215 
   269         append to the INSERT query. The returned fragment should
   268         append to the INSERT query. The returned fragment should
   270         contain a format string to hold the appropriate column.
   269         contain a format string to hold the appropriate column.
   271         """
   270         """
   272         pass
   271         pass
   273 
   272 
   274     def query_class(self, DefaultQueryClass):
   273     def compiler(self, compiler_name):
   275         """
   274         """
   276         Given the default Query class, returns a custom Query class
   275         Returns the SQLCompiler class corresponding to the given name,
   277         to use for this backend. Returns None if a custom Query isn't used.
   276         in the namespace corresponding to the `compiler_module` attribute
   278         See also BaseDatabaseFeatures.uses_custom_query_class, which regulates
   277         on this backend.
   279         whether this method is called at all.
   278         """
   280         """
   279         if compiler_name not in self._cache:
   281         return None
   280             self._cache[compiler_name] = getattr(
       
   281                 import_module(self.compiler_module), compiler_name
       
   282             )
       
   283         return self._cache[compiler_name]
   282 
   284 
   283     def quote_name(self, name):
   285     def quote_name(self, name):
   284         """
   286         """
   285         Returns a quoted version of the given table, index or column name. Does
   287         Returns a quoted version of the given table, index or column name. Does
   286         not quote the given name if it's already been quoted.
   288         not quote the given name if it's already been quoted.
   496         are in INSTALLED_APPS.
   498         are in INSTALLED_APPS.
   497 
   499 
   498         If only_existing is True, the resulting list will only include the tables
   500         If only_existing is True, the resulting list will only include the tables
   499         that actually exist in the database.
   501         that actually exist in the database.
   500         """
   502         """
   501         from django.db import models
   503         from django.db import models, router
   502         tables = set()
   504         tables = set()
   503         for app in models.get_apps():
   505         for app in models.get_apps():
   504             for model in models.get_models(app):
   506             for model in models.get_models(app):
   505                 if not model._meta.managed:
   507                 if not model._meta.managed:
       
   508                     continue
       
   509                 if not router.allow_syncdb(self.connection.alias, model):
   506                     continue
   510                     continue
   507                 tables.add(model._meta.db_table)
   511                 tables.add(model._meta.db_table)
   508                 tables.update([f.m2m_db_table() for f in model._meta.local_many_to_many])
   512                 tables.update([f.m2m_db_table() for f in model._meta.local_many_to_many])
   509         if only_existing:
   513         if only_existing:
   510             tables = [t for t in tables if self.table_name_converter(t) in self.table_names()]
   514             tables = [t for t in tables if self.table_name_converter(t) in self.table_names()]
   511         return tables
   515         return tables
   512 
   516 
   513     def installed_models(self, tables):
   517     def installed_models(self, tables):
   514         "Returns a set of all models represented by the provided list of table names."
   518         "Returns a set of all models represented by the provided list of table names."
   515         from django.db import models
   519         from django.db import models, router
   516         all_models = []
   520         all_models = []
   517         for app in models.get_apps():
   521         for app in models.get_apps():
   518             for model in models.get_models(app):
   522             for model in models.get_models(app):
   519                 all_models.append(model)
   523                 if router.allow_syncdb(self.connection.alias, model):
       
   524                     all_models.append(model)
   520         return set([m for m in all_models
   525         return set([m for m in all_models
   521             if self.table_name_converter(m._meta.db_table) in map(self.table_name_converter, tables)
   526             if self.table_name_converter(m._meta.db_table) in map(self.table_name_converter, tables)
   522         ])
   527         ])
   523 
   528 
   524     def sequence_list(self):
   529     def sequence_list(self):
   525         "Returns a list of information about all DB sequences for all models in all apps."
   530         "Returns a list of information about all DB sequences for all models in all apps."
   526         from django.db import models
   531         from django.db import models, router
   527 
   532 
   528         apps = models.get_apps()
   533         apps = models.get_apps()
   529         sequence_list = []
   534         sequence_list = []
   530 
   535 
   531         for app in apps:
   536         for app in apps:
   532             for model in models.get_models(app):
   537             for model in models.get_models(app):
   533                 if not model._meta.managed:
   538                 if not model._meta.managed:
       
   539                     continue
       
   540                 if not router.allow_syncdb(self.connection.alias, model):
   534                     continue
   541                     continue
   535                 for f in model._meta.local_fields:
   542                 for f in model._meta.local_fields:
   536                     if isinstance(f, models.AutoField):
   543                     if isinstance(f, models.AutoField):
   537                         sequence_list.append({'table': model._meta.db_table, 'column': f.column})
   544                         sequence_list.append({'table': model._meta.db_table, 'column': f.column})
   538                         break # Only one AutoField is allowed per model, so don't bother continuing.
   545                         break # Only one AutoField is allowed per model, so don't bother continuing.
   563 
   570 
   564 class BaseDatabaseValidation(object):
   571 class BaseDatabaseValidation(object):
   565     """
   572     """
   566     This class encapsualtes all backend-specific model validation.
   573     This class encapsualtes all backend-specific model validation.
   567     """
   574     """
       
   575     def __init__(self, connection):
       
   576         self.connection = connection
       
   577 
   568     def validate_field(self, errors, opts, f):
   578     def validate_field(self, errors, opts, f):
   569         "By default, there is no backend-specific validation"
   579         "By default, there is no backend-specific validation"
   570         pass
   580         pass