diff options
| author | Adrian Holovaty <adrian@holovaty.com> | 2007-08-20 05:00:52 +0000 |
|---|---|---|
| committer | Adrian Holovaty <adrian@holovaty.com> | 2007-08-20 05:00:52 +0000 |
| commit | c49f2d21ea055ae3c9b66cfd62a9f527a2f6d3b5 (patch) | |
| tree | 66a8709e51ae865b2a115a5f3753f2460d9b281c /django/db/backends/sqlite3 | |
| parent | 0ae4e102dc60de49d8f1457373458082f6639086 (diff) | |
newforms-admin: Merged to [5983]
git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@5984 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/db/backends/sqlite3')
| -rw-r--r-- | django/db/backends/sqlite3/base.py | 206 | ||||
| -rw-r--r-- | django/db/backends/sqlite3/introspection.py | 4 |
2 files changed, 69 insertions, 141 deletions
diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py index a0b1341b53..7919e1cc50 100644 --- a/django/db/backends/sqlite3/base.py +++ b/django/db/backends/sqlite3/base.py @@ -2,7 +2,7 @@ SQLite3 backend for django. Requires pysqlite2 (http://pysqlite.org/). """ -from django.db.backends import util +from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, util try: try: from sqlite3 import dbapi2 as Database @@ -34,21 +34,69 @@ Database.register_converter("TIMESTAMP", util.typecast_timestamp) Database.register_converter("decimal", util.typecast_decimal) Database.register_adapter(decimal.Decimal, util.rev_typecast_decimal) -try: - # Only exists in Python 2.4+ - from threading import local -except ImportError: - # Import copy of _thread_local.py from Python 2.4 - from django.utils._threading_local import local +class DatabaseFeatures(BaseDatabaseFeatures): + supports_constraints = False -class DatabaseWrapper(local): - def __init__(self, **kwargs): - self.connection = None - self.queries = [] - self.options = kwargs +class DatabaseOperations(BaseDatabaseOperations): + def date_extract_sql(self, lookup_type, field_name): + # sqlite doesn't support extract, so we fake it with the user-defined + # function django_extract that's registered in connect(). + return 'django_extract("%s", %s)' % (lookup_type.lower(), field_name) - def cursor(self): - from django.conf import settings + def date_trunc_sql(self, lookup_type, field_name): + # sqlite doesn't support DATE_TRUNC, so we fake it with a user-defined + # function django_date_trunc that's registered in connect(). + return 'django_date_trunc("%s", %s)' % (lookup_type.lower(), field_name) + + def drop_foreignkey_sql(self): + return "" + + def pk_default_value(self): + return 'NULL' + + def quote_name(self, name): + if name.startswith('"') and name.endswith('"'): + return name # Quoting once is enough. + return '"%s"' % name + + def sql_flush(self, style, tables, sequences): + # NB: The generated SQL below is specific to SQLite + # Note: The DELETE FROM... SQL generated below works for SQLite databases + # because constraints don't exist + sql = ['%s %s %s;' % \ + (style.SQL_KEYWORD('DELETE'), + style.SQL_KEYWORD('FROM'), + style.SQL_FIELD(self.quote_name(table)) + ) for table in tables] + # Note: No requirement for reset of auto-incremented indices (cf. other + # sql_flush() implementations). Just return SQL at this point + return sql + +class DatabaseWrapper(BaseDatabaseWrapper): + features = DatabaseFeatures() + ops = DatabaseOperations() + + # SQLite requires LIKE statements to include an ESCAPE clause if the value + # being escaped has a percent or underscore in it. + # See http://www.sqlite.org/lang_expr.html for an explanation. + operators = { + 'exact': '= %s', + 'iexact': "LIKE %s ESCAPE '\\'", + 'contains': "LIKE %s ESCAPE '\\'", + 'icontains': "LIKE %s ESCAPE '\\'", + 'regex': 'REGEXP %s', + 'iregex': "REGEXP '(?i)' || %s", + 'gt': '> %s', + 'gte': '>= %s', + 'lt': '< %s', + 'lte': '<= %s', + 'startswith': "LIKE %s ESCAPE '\\'", + 'endswith': "LIKE %s ESCAPE '\\'", + 'istartswith': "LIKE %s ESCAPE '\\'", + 'iendswith': "LIKE %s ESCAPE '\\'", + } + + def _cursor(self, settings): if self.connection is None: kwargs = { 'database': settings.DATABASE_NAME, @@ -60,28 +108,15 @@ class DatabaseWrapper(local): self.connection.create_function("django_extract", 2, _sqlite_extract) self.connection.create_function("django_date_trunc", 2, _sqlite_date_trunc) self.connection.create_function("regexp", 2, _sqlite_regexp) - cursor = self.connection.cursor(factory=SQLiteCursorWrapper) - if settings.DEBUG: - return util.CursorDebugWrapper(cursor, self) - else: - return cursor - - def _commit(self): - if self.connection is not None: - self.connection.commit() - - def _rollback(self): - if self.connection is not None: - self.connection.rollback() + return self.connection.cursor(factory=SQLiteCursorWrapper) def close(self): from django.conf import settings # If database is in memory, closing the connection destroys the - # database. To prevent accidental data loss, ignore close requests on + # database. To prevent accidental data loss, ignore close requests on # an in-memory db. - if self.connection is not None and settings.DATABASE_NAME != ":memory:": - self.connection.close() - self.connection = None + if settings.DATABASE_NAME != ":memory:": + BaseDatabaseWrapper.close(self) class SQLiteCursorWrapper(Database.Cursor): """ @@ -100,33 +135,6 @@ class SQLiteCursorWrapper(Database.Cursor): def convert_query(self, query, num_params): return query % tuple("?" * num_params) -allows_group_by_ordinal = True -allows_unique_and_pk = True -autoindexes_primary_keys = True -needs_datetime_string_cast = True -needs_upper_for_iops = False -supports_constraints = False -supports_tablespaces = False -uses_case_insensitive_names = False - -def quote_name(name): - if name.startswith('"') and name.endswith('"'): - return name # Quoting once is enough. - return '"%s"' % name - -dictfetchone = util.dictfetchone -dictfetchmany = util.dictfetchmany -dictfetchall = util.dictfetchall - -def get_last_insert_id(cursor, table_name, pk_name): - return cursor.lastrowid - -def get_date_extract_sql(lookup_type, table_name): - # lookup_type is 'year', 'month', 'day' - # sqlite doesn't support extract, so we fake it with the user-defined - # function _sqlite_extract that's registered in connect(), above. - return 'django_extract("%s", %s)' % (lookup_type.lower(), table_name) - def _sqlite_extract(lookup_type, dt): try: dt = util.typecast_timestamp(dt) @@ -134,67 +142,6 @@ def _sqlite_extract(lookup_type, dt): return None return str(getattr(dt, lookup_type)) -def get_date_trunc_sql(lookup_type, field_name): - # lookup_type is 'year', 'month', 'day' - # sqlite doesn't support DATE_TRUNC, so we fake it as above. - return 'django_date_trunc("%s", %s)' % (lookup_type.lower(), field_name) - -def get_datetime_cast_sql(): - return None - -def get_limit_offset_sql(limit, offset=None): - sql = "LIMIT %s" % limit - if offset and offset != 0: - sql += " OFFSET %s" % offset - return sql - -def get_random_function_sql(): - return "RANDOM()" - -def get_deferrable_sql(): - return "" - -def get_fulltext_search_sql(field_name): - raise NotImplementedError - -def get_drop_foreignkey_sql(): - return "" - -def get_pk_default_value(): - return "NULL" - -def get_max_name_length(): - return None - -def get_start_transaction_sql(): - return "BEGIN;" - -def get_autoinc_sql(table): - return None - -def get_sql_flush(style, tables, sequences): - """ - Return a list of SQL statements required to remove all data from - all tables in the database (without actually removing the tables - themselves) and put the database in an empty 'initial' state - """ - # NB: The generated SQL below is specific to SQLite - # Note: The DELETE FROM... SQL generated below works for SQLite databases - # because constraints don't exist - sql = ['%s %s %s;' % \ - (style.SQL_KEYWORD('DELETE'), - style.SQL_KEYWORD('FROM'), - style.SQL_FIELD(quote_name(table)) - ) for table in tables] - # Note: No requirement for reset of auto-incremented indices (cf. other - # get_sql_flush() implementations). Just return SQL at this point - return sql - -def get_sql_sequence_reset(style, model_list): - "Returns a list of the SQL statements to reset sequences for the given models." - # No sequence reset required - return [] - def _sqlite_date_trunc(lookup_type, dt): try: dt = util.typecast_timestamp(dt) @@ -213,24 +160,3 @@ def _sqlite_regexp(re_pattern, re_string): return bool(re.search(re_pattern, re_string)) except: return False - -# SQLite requires LIKE statements to include an ESCAPE clause if the value -# being escaped has a percent or underscore in it. -# See http://www.sqlite.org/lang_expr.html for an explanation. -OPERATOR_MAPPING = { - 'exact': '= %s', - 'iexact': "LIKE %s ESCAPE '\\'", - 'contains': "LIKE %s ESCAPE '\\'", - 'icontains': "LIKE %s ESCAPE '\\'", - 'regex': 'REGEXP %s', - 'iregex': "REGEXP '(?i)' || %s", - 'gt': '> %s', - 'gte': '>= %s', - 'lt': '< %s', - 'lte': '<= %s', - 'startswith': "LIKE %s ESCAPE '\\'", - 'endswith': "LIKE %s ESCAPE '\\'", - 'istartswith': "LIKE %s ESCAPE '\\'", - 'iendswith': "LIKE %s ESCAPE '\\'", -} - diff --git a/django/db/backends/sqlite3/introspection.py b/django/db/backends/sqlite3/introspection.py index cb2fbb8ee0..52b880aac2 100644 --- a/django/db/backends/sqlite3/introspection.py +++ b/django/db/backends/sqlite3/introspection.py @@ -1,4 +1,6 @@ -from django.db.backends.sqlite3.base import quote_name +from django.db.backends.sqlite3.base import DatabaseOperations + +quote_name = DatabaseOperations().quote_name def get_table_list(cursor): "Returns a list of table names in the current database." |
