2 PostgreSQL database backend for Django. |
2 PostgreSQL database backend for Django. |
3 |
3 |
4 Requires psycopg 1: http://initd.org/projects/psycopg1 |
4 Requires psycopg 1: http://initd.org/projects/psycopg1 |
5 """ |
5 """ |
6 |
6 |
|
7 from django.db.backends import * |
|
8 from django.db.backends.postgresql.client import DatabaseClient |
|
9 from django.db.backends.postgresql.creation import DatabaseCreation |
|
10 from django.db.backends.postgresql.introspection import DatabaseIntrospection |
|
11 from django.db.backends.postgresql.operations import DatabaseOperations |
|
12 from django.db.backends.postgresql.version import get_version |
7 from django.utils.encoding import smart_str, smart_unicode |
13 from django.utils.encoding import smart_str, smart_unicode |
8 from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, util |
14 |
9 from django.db.backends.postgresql.operations import DatabaseOperations |
|
10 try: |
15 try: |
11 import psycopg as Database |
16 import psycopg as Database |
12 except ImportError, e: |
17 except ImportError, e: |
13 from django.core.exceptions import ImproperlyConfigured |
18 from django.core.exceptions import ImproperlyConfigured |
14 raise ImproperlyConfigured("Error loading psycopg module: %s" % e) |
19 raise ImproperlyConfigured("Error loading psycopg module: %s" % e) |
58 |
63 |
59 def __iter__(self): |
64 def __iter__(self): |
60 return iter(self.cursor) |
65 return iter(self.cursor) |
61 |
66 |
62 class DatabaseFeatures(BaseDatabaseFeatures): |
67 class DatabaseFeatures(BaseDatabaseFeatures): |
63 pass # This backend uses all the defaults. |
68 uses_savepoints = True |
64 |
69 |
65 class DatabaseWrapper(BaseDatabaseWrapper): |
70 class DatabaseWrapper(BaseDatabaseWrapper): |
66 features = DatabaseFeatures() |
|
67 ops = DatabaseOperations() |
|
68 operators = { |
71 operators = { |
69 'exact': '= %s', |
72 'exact': '= %s', |
70 'iexact': 'ILIKE %s', |
73 'iexact': '= UPPER(%s)', |
71 'contains': 'LIKE %s', |
74 'contains': 'LIKE %s', |
72 'icontains': 'ILIKE %s', |
75 'icontains': 'LIKE UPPER(%s)', |
73 'regex': '~ %s', |
76 'regex': '~ %s', |
74 'iregex': '~* %s', |
77 'iregex': '~* %s', |
75 'gt': '> %s', |
78 'gt': '> %s', |
76 'gte': '>= %s', |
79 'gte': '>= %s', |
77 'lt': '< %s', |
80 'lt': '< %s', |
78 'lte': '<= %s', |
81 'lte': '<= %s', |
79 'startswith': 'LIKE %s', |
82 'startswith': 'LIKE %s', |
80 'endswith': 'LIKE %s', |
83 'endswith': 'LIKE %s', |
81 'istartswith': 'ILIKE %s', |
84 'istartswith': 'LIKE UPPER(%s)', |
82 'iendswith': 'ILIKE %s', |
85 'iendswith': 'LIKE UPPER(%s)', |
83 } |
86 } |
|
87 |
|
88 def __init__(self, *args, **kwargs): |
|
89 super(DatabaseWrapper, self).__init__(*args, **kwargs) |
|
90 |
|
91 self.features = DatabaseFeatures() |
|
92 self.ops = DatabaseOperations() |
|
93 self.client = DatabaseClient() |
|
94 self.creation = DatabaseCreation(self) |
|
95 self.introspection = DatabaseIntrospection(self) |
|
96 self.validation = BaseDatabaseValidation() |
84 |
97 |
85 def _cursor(self, settings): |
98 def _cursor(self, settings): |
86 set_tz = False |
99 set_tz = False |
87 if self.connection is None: |
100 if self.connection is None: |
88 set_tz = True |
101 set_tz = True |
101 self.connection = Database.connect(conn_string, **self.options) |
114 self.connection = Database.connect(conn_string, **self.options) |
102 self.connection.set_isolation_level(1) # make transactions transparent to all cursors |
115 self.connection.set_isolation_level(1) # make transactions transparent to all cursors |
103 cursor = self.connection.cursor() |
116 cursor = self.connection.cursor() |
104 if set_tz: |
117 if set_tz: |
105 cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE]) |
118 cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE]) |
|
119 if not hasattr(self, '_version'): |
|
120 self.__class__._version = get_version(cursor) |
|
121 if self._version < (8, 0): |
|
122 # No savepoint support for earlier version of PostgreSQL. |
|
123 self.features.uses_savepoints = False |
106 cursor.execute("SET client_encoding to 'UNICODE'") |
124 cursor.execute("SET client_encoding to 'UNICODE'") |
107 cursor = UnicodeCursorWrapper(cursor, 'utf-8') |
125 cursor = UnicodeCursorWrapper(cursor, 'utf-8') |
108 return cursor |
126 return cursor |
109 |
127 |
110 def typecast_string(s): |
128 def typecast_string(s): |