summaryrefslogtreecommitdiff
path: root/django/db/backends/sqlite3/base.py
diff options
context:
space:
mode:
authorDerek Anderson <public@kered.org>2007-07-20 20:49:49 +0000
committerDerek Anderson <public@kered.org>2007-07-20 20:49:49 +0000
commit365f4b869800469ba786919f11422c73b3ec9fbb (patch)
treebc45d8db548a35b99c54600e0c4fde9ca87b35bc /django/db/backends/sqlite3/base.py
parent42851d90dadbf62f5d342ce5c4f496ba1eeba987 (diff)
schema-evolution: merged trunk:HEAD into schema-evolution branch
git-svn-id: http://code.djangoproject.com/svn/django/branches/schema-evolution@5734 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/db/backends/sqlite3/base.py')
-rw-r--r--django/db/backends/sqlite3/base.py140
1 files changed, 78 insertions, 62 deletions
diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py
index 01e4b3aebf..a0b1341b53 100644
--- a/django/db/backends/sqlite3/base.py
+++ b/django/db/backends/sqlite3/base.py
@@ -17,7 +17,13 @@ except ImportError, e:
module = 'sqlite3'
raise ImproperlyConfigured, "Error loading %s module: %s" % (module, e)
+try:
+ import decimal
+except ImportError:
+ from django.utils import _decimal as decimal # for Python 2.3
+
DatabaseError = Database.DatabaseError
+IntegrityError = Database.IntegrityError
Database.register_converter("bool", lambda s: str(s) == '1')
Database.register_converter("time", util.typecast_time)
@@ -25,14 +31,8 @@ Database.register_converter("date", util.typecast_date)
Database.register_converter("datetime", util.typecast_timestamp)
Database.register_converter("timestamp", util.typecast_timestamp)
Database.register_converter("TIMESTAMP", util.typecast_timestamp)
-
-def utf8rowFactory(cursor, row):
- def utf8(s):
- if type(s) == unicode:
- return s.encode("utf-8")
- else:
- return s
- return [utf8(r) for r in row]
+Database.register_converter("decimal", util.typecast_decimal)
+Database.register_adapter(decimal.Decimal, util.rev_typecast_decimal)
try:
# Only exists in Python 2.4+
@@ -42,37 +42,43 @@ except ImportError:
from django.utils._threading_local import local
class DatabaseWrapper(local):
- def __init__(self):
+ def __init__(self, **kwargs):
self.connection = None
self.queries = []
+ self.options = kwargs
def cursor(self):
from django.conf import settings
if self.connection is None:
- self.connection = Database.connect(settings.DATABASE_NAME,
- detect_types=Database.PARSE_DECLTYPES | Database.PARSE_COLNAMES)
-
- # Register extract and date_trunc functions.
+ kwargs = {
+ 'database': settings.DATABASE_NAME,
+ 'detect_types': Database.PARSE_DECLTYPES | Database.PARSE_COLNAMES,
+ }
+ kwargs.update(self.options)
+ self.connection = Database.connect(**kwargs)
+ # Register extract, date_trunc, and regexp functions.
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)
- cursor.row_factory = utf8rowFactory
if settings.DEBUG:
return util.CursorDebugWrapper(cursor, self)
else:
return cursor
def _commit(self):
- self.connection.commit()
+ if self.connection is not None:
+ self.connection.commit()
def _rollback(self):
- if self.connection:
+ if self.connection is not None:
self.connection.rollback()
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 an in-memory db.
+ # If database is in memory, closing the connection destroys the
+ # 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
@@ -94,7 +100,14 @@ 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('"'):
@@ -126,6 +139,9 @@ def get_date_trunc_sql(lookup_type, field_name):
# 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:
@@ -135,6 +151,9 @@ def get_limit_offset_sql(limit, offset=None):
def get_random_function_sql():
return "RANDOM()"
+def get_deferrable_sql():
+ return ""
+
def get_fulltext_search_sql(field_name):
raise NotImplementedError
@@ -144,6 +163,38 @@ def get_drop_foreignkey_sql():
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)
@@ -156,50 +207,12 @@ def _sqlite_date_trunc(lookup_type, dt):
elif lookup_type == 'day':
return "%i-%02i-%02i 00:00:00" % (dt.year, dt.month, dt.day)
-def get_change_column_name_sql( table_name, indexes, old_col_name, new_col_name, col_def ):
- # sqlite doesn't support column renames, so we fake it
- # TODO: only supports a single primary key so far
- pk_name = None
- for key in indexes.keys():
- if indexes[key]['primary_key']: pk_name = key
- output = []
- output.append( 'ALTER TABLE '+ quote_name(table_name) +' ADD COLUMN '+ quote_name(new_col_name) +' '+ col_def + ';' )
- output.append( 'UPDATE '+ quote_name(table_name) +' SET '+ new_col_name +' = '+ old_col_name +' WHERE '+ pk_name +'=(select '+ pk_name +' from '+ table_name +');' )
- output.append( '-- FYI: sqlite does not support deleting columns, so '+ quote_name(old_col_name) +' remains as cruft' )
- # use the following when sqlite gets drop support
- #output.append( 'ALTER TABLE '+ quote_name(table_name) +' DROP COLUMN '+ quote_name(old_col_name) )
- return '\n'.join(output)
-
-def get_change_column_def_sql( table_name, col_name, col_def ):
- # sqlite doesn't support column modifications, so we fake it
- output = []
- # TODO: fake via renaming the table, building a new one and deleting the old
- output.append('-- sqlite does not support column modifications '+ quote_name(table_name) +'.'+ quote_name(col_name) +' to '+ col_def)
- return '\n'.join(output)
-
-def get_add_column_sql( table_name, col_name, col_type, null, unique, primary_key ):
- output = []
- field_output = []
- field_output.append('ALTER TABLE')
- field_output.append(quote_name(table_name))
- field_output.append('ADD COLUMN')
- field_output.append(quote_name(col_name))
- field_output.append(col_type)
- field_output.append(('%sNULL' % (not null and 'NOT ' or '')))
- if unique:
- field_output.append(('UNIQUE'))
- if primary_key:
- field_output.append(('PRIMARY KEY'))
- output.append(' '.join(field_output) + ';')
- return '\n'.join(output)
-
-def get_drop_column_sql( table_name, col_name ):
- output = []
- output.append( '-- FYI: sqlite does not support deleting columns, so '+ quote_name(old_col_name) +' remains as cruft' )
- # use the following when sqlite gets drop support
- # output.append( '-- ALTER TABLE '+ quote_name(table_name) +' DROP COLUMN '+ quote_name(col_name) )
- return '\n'.join(output)
-
+def _sqlite_regexp(re_pattern, re_string):
+ import re
+ try:
+ 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.
@@ -209,6 +222,8 @@ OPERATOR_MAPPING = {
'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',
@@ -218,3 +233,4 @@ OPERATOR_MAPPING = {
'istartswith': "LIKE %s ESCAPE '\\'",
'iendswith': "LIKE %s ESCAPE '\\'",
}
+