25 IntegrityError = Database.IntegrityError |
27 IntegrityError = Database.IntegrityError |
26 |
28 |
27 psycopg2.extensions.register_type(psycopg2.extensions.UNICODE) |
29 psycopg2.extensions.register_type(psycopg2.extensions.UNICODE) |
28 psycopg2.extensions.register_adapter(SafeString, psycopg2.extensions.QuotedString) |
30 psycopg2.extensions.register_adapter(SafeString, psycopg2.extensions.QuotedString) |
29 psycopg2.extensions.register_adapter(SafeUnicode, psycopg2.extensions.QuotedString) |
31 psycopg2.extensions.register_adapter(SafeUnicode, psycopg2.extensions.QuotedString) |
|
32 |
|
33 class CursorWrapper(object): |
|
34 """ |
|
35 A thin wrapper around psycopg2's normal cursor class so that we can catch |
|
36 particular exception instances and reraise them with the right types. |
|
37 """ |
|
38 |
|
39 def __init__(self, cursor): |
|
40 self.cursor = cursor |
|
41 |
|
42 def execute(self, query, args=None): |
|
43 try: |
|
44 return self.cursor.execute(query, args) |
|
45 except Database.IntegrityError, e: |
|
46 raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2] |
|
47 except Database.DatabaseError, e: |
|
48 raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2] |
|
49 |
|
50 def executemany(self, query, args): |
|
51 try: |
|
52 return self.cursor.executemany(query, args) |
|
53 except Database.IntegrityError, e: |
|
54 raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2] |
|
55 except Database.DatabaseError, e: |
|
56 raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2] |
|
57 |
|
58 def __getattr__(self, attr): |
|
59 if attr in self.__dict__: |
|
60 return self.__dict__[attr] |
|
61 else: |
|
62 return getattr(self.cursor, attr) |
|
63 |
|
64 def __iter__(self): |
|
65 return iter(self.cursor) |
30 |
66 |
31 class DatabaseFeatures(BaseDatabaseFeatures): |
67 class DatabaseFeatures(BaseDatabaseFeatures): |
32 needs_datetime_string_cast = False |
68 needs_datetime_string_cast = False |
33 can_return_id_from_insert = False |
69 can_return_id_from_insert = False |
34 |
70 |
62 |
98 |
63 def __init__(self, *args, **kwargs): |
99 def __init__(self, *args, **kwargs): |
64 super(DatabaseWrapper, self).__init__(*args, **kwargs) |
100 super(DatabaseWrapper, self).__init__(*args, **kwargs) |
65 |
101 |
66 self.features = DatabaseFeatures() |
102 self.features = DatabaseFeatures() |
67 autocommit = self.settings_dict["DATABASE_OPTIONS"].get('autocommit', False) |
103 autocommit = self.settings_dict["OPTIONS"].get('autocommit', False) |
68 self.features.uses_autocommit = autocommit |
104 self.features.uses_autocommit = autocommit |
69 self._set_isolation_level(int(not autocommit)) |
105 self._set_isolation_level(int(not autocommit)) |
70 self.ops = DatabaseOperations() |
106 self.ops = DatabaseOperations(self) |
71 self.client = DatabaseClient(self) |
107 self.client = DatabaseClient(self) |
72 self.creation = DatabaseCreation(self) |
108 self.creation = DatabaseCreation(self) |
73 self.introspection = DatabaseIntrospection(self) |
109 self.introspection = DatabaseIntrospection(self) |
74 self.validation = BaseDatabaseValidation() |
110 self.validation = BaseDatabaseValidation(self) |
75 |
111 |
76 def _cursor(self): |
112 def _cursor(self): |
|
113 new_connection = False |
77 set_tz = False |
114 set_tz = False |
78 settings_dict = self.settings_dict |
115 settings_dict = self.settings_dict |
79 if self.connection is None: |
116 if self.connection is None: |
80 set_tz = True |
117 new_connection = True |
81 if settings_dict['DATABASE_NAME'] == '': |
118 set_tz = settings_dict.get('TIME_ZONE') |
|
119 if settings_dict['NAME'] == '': |
82 from django.core.exceptions import ImproperlyConfigured |
120 from django.core.exceptions import ImproperlyConfigured |
83 raise ImproperlyConfigured("You need to specify DATABASE_NAME in your Django settings file.") |
121 raise ImproperlyConfigured("You need to specify NAME in your Django settings file.") |
84 conn_params = { |
122 conn_params = { |
85 'database': settings_dict['DATABASE_NAME'], |
123 'database': settings_dict['NAME'], |
86 } |
124 } |
87 conn_params.update(settings_dict['DATABASE_OPTIONS']) |
125 conn_params.update(settings_dict['OPTIONS']) |
88 if 'autocommit' in conn_params: |
126 if 'autocommit' in conn_params: |
89 del conn_params['autocommit'] |
127 del conn_params['autocommit'] |
90 if settings_dict['DATABASE_USER']: |
128 if settings_dict['USER']: |
91 conn_params['user'] = settings_dict['DATABASE_USER'] |
129 conn_params['user'] = settings_dict['USER'] |
92 if settings_dict['DATABASE_PASSWORD']: |
130 if settings_dict['PASSWORD']: |
93 conn_params['password'] = settings_dict['DATABASE_PASSWORD'] |
131 conn_params['password'] = settings_dict['PASSWORD'] |
94 if settings_dict['DATABASE_HOST']: |
132 if settings_dict['HOST']: |
95 conn_params['host'] = settings_dict['DATABASE_HOST'] |
133 conn_params['host'] = settings_dict['HOST'] |
96 if settings_dict['DATABASE_PORT']: |
134 if settings_dict['PORT']: |
97 conn_params['port'] = settings_dict['DATABASE_PORT'] |
135 conn_params['port'] = settings_dict['PORT'] |
98 self.connection = Database.connect(**conn_params) |
136 self.connection = Database.connect(**conn_params) |
99 self.connection.set_client_encoding('UTF8') |
137 self.connection.set_client_encoding('UTF8') |
100 self.connection.set_isolation_level(self.isolation_level) |
138 self.connection.set_isolation_level(self.isolation_level) |
101 connection_created.send(sender=self.__class__) |
139 connection_created.send(sender=self.__class__) |
102 cursor = self.connection.cursor() |
140 cursor = self.connection.cursor() |
103 cursor.tzinfo_factory = None |
141 cursor.tzinfo_factory = None |
104 if set_tz: |
142 if new_connection: |
105 cursor.execute("SET TIME ZONE %s", [settings_dict['TIME_ZONE']]) |
143 if set_tz: |
|
144 cursor.execute("SET TIME ZONE %s", [settings_dict['TIME_ZONE']]) |
106 if not hasattr(self, '_version'): |
145 if not hasattr(self, '_version'): |
107 self.__class__._version = get_version(cursor) |
146 self.__class__._version = get_version(cursor) |
108 if self._version[0:2] < (8, 0): |
147 if self._version[0:2] < (8, 0): |
109 # No savepoint support for earlier version of PostgreSQL. |
148 # No savepoint support for earlier version of PostgreSQL. |
110 self.features.uses_savepoints = False |
149 self.features.uses_savepoints = False |
117 else: |
156 else: |
118 # FIXME: Eventually we're enable this by default for |
157 # FIXME: Eventually we're enable this by default for |
119 # versions that support it, but, right now, that's hard to |
158 # versions that support it, but, right now, that's hard to |
120 # do without breaking other things (#10509). |
159 # do without breaking other things (#10509). |
121 self.features.can_return_id_from_insert = True |
160 self.features.can_return_id_from_insert = True |
122 return cursor |
161 return CursorWrapper(cursor) |
123 |
162 |
124 def _enter_transaction_management(self, managed): |
163 def _enter_transaction_management(self, managed): |
125 """ |
164 """ |
126 Switch the isolation level when needing transaction support, so that |
165 Switch the isolation level when needing transaction support, so that |
127 the same transaction is visible across all the queries. |
166 the same transaction is visible across all the queries. |