web/lib/django/db/backends/sqlite3/base.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
     1 """
     1 """
     2 SQLite3 backend for django.
     2 SQLite3 backend for django.
     3 
     3 
     4 Python 2.3 and 2.4 require pysqlite2 (http://pysqlite.org/).
     4 Python 2.4 requires pysqlite2 (http://pysqlite.org/).
     5 
     5 
     6 Python 2.5 and later can use a pysqlite2 module or the sqlite3 module in the
     6 Python 2.5 and later can use a pysqlite2 module or the sqlite3 module in the
     7 standard library.
     7 standard library.
     8 """
     8 """
     9 
     9 
       
    10 import re
       
    11 import sys
       
    12 
       
    13 from django.db import utils
    10 from django.db.backends import *
    14 from django.db.backends import *
    11 from django.db.backends.signals import connection_created
    15 from django.db.backends.signals import connection_created
    12 from django.db.backends.sqlite3.client import DatabaseClient
    16 from django.db.backends.sqlite3.client import DatabaseClient
    13 from django.db.backends.sqlite3.creation import DatabaseCreation
    17 from django.db.backends.sqlite3.creation import DatabaseCreation
    14 from django.db.backends.sqlite3.introspection import DatabaseIntrospection
    18 from django.db.backends.sqlite3.introspection import DatabaseIntrospection
    25     if sys.version_info < (2, 5, 0):
    29     if sys.version_info < (2, 5, 0):
    26         module = 'pysqlite2 module'
    30         module = 'pysqlite2 module'
    27         exc = e1
    31         exc = e1
    28     else:
    32     else:
    29         module = 'either pysqlite2 or sqlite3 modules (tried in that order)'
    33         module = 'either pysqlite2 or sqlite3 modules (tried in that order)'
    30     raise ImproperlyConfigured, "Error loading %s: %s" % (module, exc)
    34     raise ImproperlyConfigured("Error loading %s: %s" % (module, exc))
    31 
    35 
    32 try:
       
    33     import decimal
       
    34 except ImportError:
       
    35     from django.utils import _decimal as decimal # for Python 2.3
       
    36 
    36 
    37 DatabaseError = Database.DatabaseError
    37 DatabaseError = Database.DatabaseError
    38 IntegrityError = Database.IntegrityError
    38 IntegrityError = Database.IntegrityError
    39 
    39 
    40 Database.register_converter("bool", lambda s: str(s) == '1')
    40 Database.register_converter("bool", lambda s: str(s) == '1')
    62     can_use_chunked_reads = False
    62     can_use_chunked_reads = False
    63 
    63 
    64 class DatabaseOperations(BaseDatabaseOperations):
    64 class DatabaseOperations(BaseDatabaseOperations):
    65     def date_extract_sql(self, lookup_type, field_name):
    65     def date_extract_sql(self, lookup_type, field_name):
    66         # sqlite doesn't support extract, so we fake it with the user-defined
    66         # sqlite doesn't support extract, so we fake it with the user-defined
    67         # function django_extract that's registered in connect().
    67         # function django_extract that's registered in connect(). Note that
    68         return 'django_extract("%s", %s)' % (lookup_type.lower(), field_name)
    68         # single quotes are used because this is a string (and could otherwise
       
    69         # cause a collision with a field name).
       
    70         return "django_extract('%s', %s)" % (lookup_type.lower(), field_name)
    69 
    71 
    70     def date_trunc_sql(self, lookup_type, field_name):
    72     def date_trunc_sql(self, lookup_type, field_name):
    71         # sqlite doesn't support DATE_TRUNC, so we fake it with a user-defined
    73         # sqlite doesn't support DATE_TRUNC, so we fake it with a user-defined
    72         # function django_date_trunc that's registered in connect().
    74         # function django_date_trunc that's registered in connect(). Note that
    73         return 'django_date_trunc("%s", %s)' % (lookup_type.lower(), field_name)
    75         # single quotes are used because this is a string (and could otherwise
       
    76         # cause a collision with a field name).
       
    77         return "django_date_trunc('%s', %s)" % (lookup_type.lower(), field_name)
    74 
    78 
    75     def drop_foreignkey_sql(self):
    79     def drop_foreignkey_sql(self):
    76         return ""
    80         return ""
    77 
    81 
    78     def pk_default_value(self):
    82     def pk_default_value(self):
   152         self.features = DatabaseFeatures()
   156         self.features = DatabaseFeatures()
   153         self.ops = DatabaseOperations()
   157         self.ops = DatabaseOperations()
   154         self.client = DatabaseClient(self)
   158         self.client = DatabaseClient(self)
   155         self.creation = DatabaseCreation(self)
   159         self.creation = DatabaseCreation(self)
   156         self.introspection = DatabaseIntrospection(self)
   160         self.introspection = DatabaseIntrospection(self)
   157         self.validation = BaseDatabaseValidation()
   161         self.validation = BaseDatabaseValidation(self)
   158 
   162 
   159     def _cursor(self):
   163     def _cursor(self):
   160         if self.connection is None:
   164         if self.connection is None:
   161             settings_dict = self.settings_dict
   165             settings_dict = self.settings_dict
   162             if not settings_dict['DATABASE_NAME']:
   166             if not settings_dict['NAME']:
   163                 from django.core.exceptions import ImproperlyConfigured
   167                 from django.core.exceptions import ImproperlyConfigured
   164                 raise ImproperlyConfigured, "Please fill out DATABASE_NAME in the settings module before using the database."
   168                 raise ImproperlyConfigured("Please fill out the database NAME in the settings module before using the database.")
   165             kwargs = {
   169             kwargs = {
   166                 'database': settings_dict['DATABASE_NAME'],
   170                 'database': settings_dict['NAME'],
   167                 'detect_types': Database.PARSE_DECLTYPES | Database.PARSE_COLNAMES,
   171                 'detect_types': Database.PARSE_DECLTYPES | Database.PARSE_COLNAMES,
   168             }
   172             }
   169             kwargs.update(settings_dict['DATABASE_OPTIONS'])
   173             kwargs.update(settings_dict['OPTIONS'])
   170             self.connection = Database.connect(**kwargs)
   174             self.connection = Database.connect(**kwargs)
   171             # Register extract, date_trunc, and regexp functions.
   175             # Register extract, date_trunc, and regexp functions.
   172             self.connection.create_function("django_extract", 2, _sqlite_extract)
   176             self.connection.create_function("django_extract", 2, _sqlite_extract)
   173             self.connection.create_function("django_date_trunc", 2, _sqlite_date_trunc)
   177             self.connection.create_function("django_date_trunc", 2, _sqlite_date_trunc)
   174             self.connection.create_function("regexp", 2, _sqlite_regexp)
   178             self.connection.create_function("regexp", 2, _sqlite_regexp)
   177 
   181 
   178     def close(self):
   182     def close(self):
   179         # If database is in memory, closing the connection destroys the
   183         # If database is in memory, closing the connection destroys the
   180         # database. To prevent accidental data loss, ignore close requests on
   184         # database. To prevent accidental data loss, ignore close requests on
   181         # an in-memory db.
   185         # an in-memory db.
   182         if self.settings_dict['DATABASE_NAME'] != ":memory:":
   186         if self.settings_dict['NAME'] != ":memory:":
   183             BaseDatabaseWrapper.close(self)
   187             BaseDatabaseWrapper.close(self)
       
   188 
       
   189 FORMAT_QMARK_REGEX = re.compile(r'(?![^%])%s')
   184 
   190 
   185 class SQLiteCursorWrapper(Database.Cursor):
   191 class SQLiteCursorWrapper(Database.Cursor):
   186     """
   192     """
   187     Django uses "format" style placeholders, but pysqlite2 uses "qmark" style.
   193     Django uses "format" style placeholders, but pysqlite2 uses "qmark" style.
   188     This fixes it -- but note that if you want to use a literal "%s" in a query,
   194     This fixes it -- but note that if you want to use a literal "%s" in a query,
   189     you'll need to use "%%s".
   195     you'll need to use "%%s".
   190     """
   196     """
   191     def execute(self, query, params=()):
   197     def execute(self, query, params=()):
   192         query = self.convert_query(query, len(params))
   198         query = self.convert_query(query)
   193         return Database.Cursor.execute(self, query, params)
   199         try:
       
   200             return Database.Cursor.execute(self, query, params)
       
   201         except Database.IntegrityError, e:
       
   202             raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
       
   203         except Database.DatabaseError, e:
       
   204             raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
   194 
   205 
   195     def executemany(self, query, param_list):
   206     def executemany(self, query, param_list):
       
   207         query = self.convert_query(query)
   196         try:
   208         try:
   197           query = self.convert_query(query, len(param_list[0]))
   209             return Database.Cursor.executemany(self, query, param_list)
   198           return Database.Cursor.executemany(self, query, param_list)
   210         except Database.IntegrityError, e:
   199         except (IndexError,TypeError):
   211             raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
   200           # No parameter list provided
   212         except Database.DatabaseError, e:
   201           return None
   213             raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
   202 
   214 
   203     def convert_query(self, query, num_params):
   215     def convert_query(self, query):
   204         return query % tuple("?" * num_params)
   216         return FORMAT_QMARK_REGEX.sub('?', query).replace('%%','%')
   205 
   217 
   206 def _sqlite_extract(lookup_type, dt):
   218 def _sqlite_extract(lookup_type, dt):
   207     if dt is None:
   219     if dt is None:
   208         return None
   220         return None
   209     try:
   221     try: