diff options
Diffstat (limited to 'django/db')
-rw-r--r-- | django/db/backends/dummy/base.py | 5 | ||||
-rw-r--r-- | django/db/backends/mysql/base.py | 2 | ||||
-rw-r--r-- | django/db/backends/mysql_old/base.py | 2 | ||||
-rw-r--r-- | django/db/backends/postgresql/base.py | 2 | ||||
-rw-r--r-- | django/db/backends/postgresql_psycopg2/base.py | 2 | ||||
-rw-r--r-- | django/db/backends/sqlite3/base.py | 12 | ||||
-rw-r--r-- | django/db/models/fields/__init__.py | 3 | ||||
-rw-r--r-- | django/db/models/query.py | 11 |
8 files changed, 37 insertions, 2 deletions
diff --git a/django/db/backends/dummy/base.py b/django/db/backends/dummy/base.py index 6a190cf59c..f47cbdf3d4 100644 --- a/django/db/backends/dummy/base.py +++ b/django/db/backends/dummy/base.py @@ -41,11 +41,16 @@ dictfetchall = complain get_last_insert_id = complain get_date_extract_sql = complain get_date_trunc_sql = complain +get_datetime_cast_sql = complain get_limit_offset_sql = complain get_random_function_sql = complain get_deferrable_sql = complain get_fulltext_search_sql = complain get_drop_foreignkey_sql = complain +get_pk_default_value = complain +get_max_name_length = ignore +get_start_transaction_sql = complain +get_autoinc_sql = complain get_sql_flush = complain get_sql_sequence_reset = complain diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py index a6d56406d6..25ae2fa84f 100644 --- a/django/db/backends/mysql/base.py +++ b/django/db/backends/mysql/base.py @@ -247,6 +247,8 @@ OPERATOR_MAPPING = { 'iexact': 'LIKE %s', 'contains': 'LIKE BINARY %s', 'icontains': 'LIKE %s', + 'regex': 'REGEXP BINARY %s', + 'iregex': 'REGEXP %s', 'gt': '> %s', 'gte': '>= %s', 'lt': '< %s', diff --git a/django/db/backends/mysql_old/base.py b/django/db/backends/mysql_old/base.py index 4a14fa822a..0a5c127e81 100644 --- a/django/db/backends/mysql_old/base.py +++ b/django/db/backends/mysql_old/base.py @@ -250,6 +250,8 @@ OPERATOR_MAPPING = { 'iexact': 'LIKE %s', 'contains': 'LIKE BINARY %s', 'icontains': 'LIKE %s', + 'regex': 'REGEXP BINARY %s', + 'iregex': 'REGEXP %s', 'gt': '> %s', 'gte': '>= %s', 'lt': '< %s', diff --git a/django/db/backends/postgresql/base.py b/django/db/backends/postgresql/base.py index e2051beaa2..d90f0cc225 100644 --- a/django/db/backends/postgresql/base.py +++ b/django/db/backends/postgresql/base.py @@ -300,6 +300,8 @@ OPERATOR_MAPPING = { 'iexact': 'ILIKE %s', 'contains': 'LIKE %s', 'icontains': 'ILIKE %s', + 'regex': '~ %s', + 'iregex': '~* %s', 'gt': '> %s', 'gte': '>= %s', 'lt': '< %s', diff --git a/django/db/backends/postgresql_psycopg2/base.py b/django/db/backends/postgresql_psycopg2/base.py index 4a9a44b3f9..c0ecbf80e9 100644 --- a/django/db/backends/postgresql_psycopg2/base.py +++ b/django/db/backends/postgresql_psycopg2/base.py @@ -229,6 +229,8 @@ OPERATOR_MAPPING = { 'iexact': 'ILIKE %s', 'contains': 'LIKE %s', 'icontains': 'ILIKE %s', + 'regex': '~ %s', + 'iregex': '~* %s', 'gt': '> %s', 'gte': '>= %s', 'lt': '< %s', diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py index d31d11fea6..a0b1341b53 100644 --- a/django/db/backends/sqlite3/base.py +++ b/django/db/backends/sqlite3/base.py @@ -56,9 +56,10 @@ class DatabaseWrapper(local): } kwargs.update(self.options) self.connection = Database.connect(**kwargs) - # Register extract and date_trunc functions. + # 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) if settings.DEBUG: return util.CursorDebugWrapper(cursor, self) @@ -206,6 +207,13 @@ 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 _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. # See http://www.sqlite.org/lang_expr.html for an explanation. @@ -214,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', diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 167155fdbb..7ef532eab6 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -175,7 +175,7 @@ class Field(object): def get_db_prep_lookup(self, lookup_type, value): "Returns field's value prepared for database lookup." - if lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte', 'month', 'day', 'search'): + if lookup_type in ('exact', 'regex', 'iregex', 'gt', 'gte', 'lt', 'lte', 'month', 'day', 'search'): return [value] elif lookup_type in ('range', 'in'): return value @@ -801,6 +801,7 @@ class IntegerField(Field): return super(IntegerField, self).formfield(**defaults) class IPAddressField(Field): + empty_strings_allowed = False def __init__(self, *args, **kwargs): kwargs['maxlength'] = 15 Field.__init__(self, *args, **kwargs) diff --git a/django/db/models/query.py b/django/db/models/query.py index 076fa15fae..5771f3d7d9 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -1,3 +1,4 @@ +from django.conf import settings from django.db import backend, connection, transaction from django.db.models.fields import DateField, FieldDoesNotExist from django.db.models import signals, loading @@ -23,6 +24,7 @@ QUERY_TERMS = ( 'gt', 'gte', 'lt', 'lte', 'in', 'startswith', 'istartswith', 'endswith', 'iendswith', 'range', 'year', 'month', 'day', 'isnull', 'search', + 'regex', 'iregex', ) # Size of each "chunk" for get_iterator calls. @@ -798,6 +800,15 @@ def get_where_clause(lookup_type, table_prefix, field_name, value): return "%s%s IS %sNULL" % (table_prefix, field_name, (not value and 'NOT ' or '')) elif lookup_type == 'search': return backend.get_fulltext_search_sql(table_prefix + field_name) + elif lookup_type in ('regex', 'iregex'): + if settings.DATABASE_ENGINE == 'oracle': + if lookup_type == 'regex': + match_option = 'c' + else: + match_option = 'i' + return "REGEXP_LIKE(%s%s, %s, '%s')" % (table_prefix, field_name, cast_sql, match_option) + else: + raise NotImplementedError raise TypeError, "Got invalid lookup_type: %s" % repr(lookup_type) def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0): |