OracleBranch: django-oracle-rev5046.diff
File django-oracle-rev5046.diff, 83.7 KB (added by , 18 years ago) |
---|
-
django/db/backends/mysql/base.py
131 131 self.server_version = tuple([int(x) for x in m.groups()]) 132 132 return self.server_version 133 133 134 allows_group_by_ordinal = True 135 allows_unique_and_pk = True 136 autoindexes_primary_keys = False 137 needs_datetime_string_cast = True # MySQLdb requires a typecast for dates 138 needs_upper_for_iops = False 134 139 supports_constraints = True 140 supports_tablespaces = False 141 uses_case_insensitive_names = False 135 142 136 143 def quote_name(name): 137 144 if name.startswith("`") and name.endswith("`"): … … 164 171 sql = "CAST(DATE_FORMAT(%s, '%s') AS DATETIME)" % (field_name, format_str) 165 172 return sql 166 173 174 def get_datetime_cast_sql(): 175 return None 176 167 177 def get_limit_offset_sql(limit, offset=None): 168 178 sql = "LIMIT " 169 179 if offset and offset != 0: … … 185 195 def get_pk_default_value(): 186 196 return "DEFAULT" 187 197 198 def get_max_name_length(): 199 return 64; 200 201 def get_start_transaction_sql(): 202 return "BEGIN;" 203 204 def get_autoinc_sql(table): 205 return None 206 188 207 def get_sql_flush(style, tables, sequences): 189 208 """Return a list of SQL statements required to remove all data from 190 209 all tables in the database (without actually removing the tables -
django/db/backends/ado_mssql/base.py
88 88 self.connection.close() 89 89 self.connection = None 90 90 91 allows_group_by_ordinal = True 92 allows_unique_and_pk = True 93 autoindexes_primary_keys = True 94 needs_datetime_string_cast = True 95 needs_upper_for_iops = False 91 96 supports_constraints = True 97 supports_tablespaces = True 98 uses_case_insensitive_names = False 92 99 93 100 def quote_name(name): 94 101 if name.startswith('[') and name.endswith(']'): … … 116 123 if lookup_type=='day': 117 124 return "Convert(datetime, Convert(varchar(12), %s))" % field_name 118 125 126 def get_datetime_cast_sql(): 127 return None 128 119 129 def get_limit_offset_sql(limit, offset=None): 120 130 # TODO: This is a guess. Make sure this is correct. 121 131 sql = "LIMIT %s" % limit … … 138 148 def get_pk_default_value(): 139 149 return "DEFAULT" 140 150 151 def get_max_name_length(): 152 return None 153 154 def get_start_transaction_sql(): 155 return "BEGIN;" 156 157 def get_tablespace_sql(tablespace, inline=False): 158 return "ON %s" % quote_name(tablespace) 159 160 def get_autoinc_sql(table): 161 return None 162 141 163 def get_sql_flush(style, tables, sequences): 142 164 """Return a list of SQL statements required to remove all data from 143 165 all tables in the database (without actually removing the tables -
django/db/backends/postgresql/base.py
104 104 self.connection.close() 105 105 self.connection = None 106 106 107 allows_group_by_ordinal = True 108 allows_unique_and_pk = True 109 autoindexes_primary_keys = True 110 needs_datetime_string_cast = True 111 needs_upper_for_iops = False 107 112 supports_constraints = True 113 supports_tablespaces = False 114 uses_case_insensitive_names = False 108 115 109 116 def quote_name(name): 110 117 if name.startswith('"') and name.endswith('"'): … … 137 144 # http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC 138 145 return "DATE_TRUNC('%s', %s)" % (lookup_type, field_name) 139 146 147 def get_datetime_cast_sql(): 148 return None 149 140 150 def get_limit_offset_sql(limit, offset=None): 141 151 sql = "LIMIT %s" % limit 142 152 if offset and offset != 0: … … 158 168 def get_pk_default_value(): 159 169 return "DEFAULT" 160 170 171 def get_max_name_length(): 172 return None 173 174 def get_start_transaction_sql(): 175 return "BEGIN;" 176 177 def get_autoinc_sql(table): 178 return None 179 161 180 def get_sql_flush(style, tables, sequences): 162 181 """Return a list of SQL statements required to remove all data from 163 182 all tables in the database (without actually removing the tables -
django/db/backends/sqlite3/base.py
99 99 def convert_query(self, query, num_params): 100 100 return query % tuple("?" * num_params) 101 101 102 allows_group_by_ordinal = True 103 allows_unique_and_pk = True 104 autoindexes_primary_keys = True 105 needs_datetime_string_cast = True 106 needs_upper_for_iops = False 102 107 supports_constraints = False 108 supports_tablespaces = False 109 uses_case_insensitive_names = False 103 110 104 111 def quote_name(name): 105 112 if name.startswith('"') and name.endswith('"'): … … 131 138 # sqlite doesn't support DATE_TRUNC, so we fake it as above. 132 139 return 'django_date_trunc("%s", %s)' % (lookup_type.lower(), field_name) 133 140 141 def get_datetime_cast_sql(): 142 return None 143 134 144 def get_limit_offset_sql(limit, offset=None): 135 145 sql = "LIMIT %s" % limit 136 146 if offset and offset != 0: … … 152 162 def get_pk_default_value(): 153 163 return "NULL" 154 164 165 def get_max_name_length(): 166 return None 167 168 def get_start_transaction_sql(): 169 return "BEGIN;" 170 171 def get_autoinc_sql(table): 172 return None 173 155 174 def get_sql_flush(style, tables, sequences): 156 175 """Return a list of SQL statements required to remove all data from 157 176 all tables in the database (without actually removing the tables -
django/db/backends/util.py
1 1 import datetime 2 import md5 2 3 from time import time 3 4 4 5 class CursorDebugWrapper(object): … … 92 93 def rev_typecast_boolean(obj, d): 93 94 return obj and '1' or '0' 94 95 96 def truncate_name(name, length=None): 97 """Shortens a string to a repeatable mangled version with the given length. 98 """ 99 if length is None or len(name) <= length: 100 return name 101 102 hash = md5.md5(name).hexdigest()[:4] 103 104 return '%s%s' % (name[:length-4], hash) 105 95 106 ################################################################################## 96 107 # Helper functions for dictfetch* for databases that don't natively support them # 97 108 ################################################################################## -
django/db/backends/oracle/base.py
4 4 Requires cx_Oracle: http://www.python.net/crew/atuining/cx_Oracle/ 5 5 """ 6 6 7 from django.conf import settings 7 8 from django.db.backends import util 8 9 try: 9 10 import cx_Oracle as Database 10 11 except ImportError, e: 11 12 from django.core.exceptions import ImproperlyConfigured 12 13 raise ImproperlyConfigured, "Error loading cx_Oracle module: %s" % e 14 import datetime 15 from django.utils.datastructures import SortedDict 13 16 17 14 18 DatabaseError = Database.Error 15 19 16 20 try: … … 30 34 return self.connection is not None 31 35 32 36 def cursor(self): 33 from django.conf import settings34 37 if not self._valid_connection(): 35 38 if len(settings.DATABASE_HOST.strip()) == 0: 36 39 settings.DATABASE_HOST = 'localhost' … … 40 43 else: 41 44 conn_string = "%s/%s@%s" % (settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME) 42 45 self.connection = Database.connect(conn_string, **self.options) 43 return FormatStylePlaceholderCursor(self.connection) 46 cursor = FormatStylePlaceholderCursor(self.connection) 47 # default arraysize of 1 is highly sub-optimal 48 cursor.arraysize = 100 49 # set oracle date to ansi date format 50 cursor.execute("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD'") 51 cursor.execute("ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'") 52 if settings.DEBUG: 53 return util.CursorDebugWrapper(cursor, self) 54 return cursor 44 55 45 56 def _commit(self): 46 57 if self.connection is not None: 47 self.connection.commit()58 return self.connection.commit() 48 59 49 60 def _rollback(self): 50 61 if self.connection is not None: 51 try: 52 self.connection.rollback() 53 except Database.NotSupportedError: 54 pass 62 return self.connection.rollback() 55 63 56 64 def close(self): 57 65 if self.connection is not None: 58 66 self.connection.close() 59 67 self.connection = None 60 68 69 allows_group_by_ordinal = False 70 allows_unique_and_pk = False # Suppress UNIQUE/PK for Oracle (ORA-02259) 71 autoindexes_primary_keys = True 72 needs_datetime_string_cast = False 73 needs_upper_for_iops = True 61 74 supports_constraints = True 75 supports_tablespaces = True 76 uses_case_insensitive_names = True 62 77 63 78 class FormatStylePlaceholderCursor(Database.Cursor): 64 79 """ … … 66 81 This fixes it -- but note that if you want to use a literal "%s" in a query, 67 82 you'll need to use "%%s". 68 83 """ 84 def _rewrite_args(self, query, params=None): 85 if params is None: 86 params = [] 87 else: 88 # cx_Oracle can't handle unicode parameters, so cast to str for now 89 for i, param in enumerate(params): 90 if type(param) == unicode: 91 try: 92 params[i] = param.encode('utf-8') 93 except UnicodeError: 94 params[i] = str(param) 95 args = [(':arg%d' % i) for i in range(len(params))] 96 query = query % tuple(args) 97 # cx_Oracle cannot execute a query with the closing ';' 98 if query.endswith(';'): 99 query = query[:-1] 100 return query, params 101 69 102 def execute(self, query, params=None): 70 if params is None: params = [] 71 query = self.convert_arguments(query, len(params)) 103 query, params = self._rewrite_args(query, params) 72 104 return Database.Cursor.execute(self, query, params) 73 105 74 106 def executemany(self, query, params=None): 75 if params is None: params = [] 76 query = self.convert_arguments(query, len(params[0])) 107 query, params = self._rewrite_args(query, params) 77 108 return Database.Cursor.executemany(self, query, params) 78 109 79 def convert_arguments(self, query, num_params):80 # replace occurances of "%s" with ":arg" - Oracle requires colons for parameter placeholders.81 args = [':arg' for i in range(num_params)]82 return query % tuple(args)83 84 110 def quote_name(name): 85 return name 111 # SQL92 requires delimited (quoted) names to be case-sensitive. When 112 # not quoted, Oracle has case-insensitive behavior for identifiers, but 113 # always defaults to uppercase. 114 # We simplify things by making Oracle identifiers always uppercase. 115 if not name.startswith('"') and not name.endswith('"'): 116 name = '"%s"' % util.truncate_name(name.upper(), get_max_name_length()) 117 return name.upper() 86 118 87 119 dictfetchone = util.dictfetchone 88 120 dictfetchmany = util.dictfetchmany 89 121 dictfetchall = util.dictfetchall 90 122 91 123 def get_last_insert_id(cursor, table_name, pk_name): 92 query = "SELECT %s_sq.currval from dual" % table_name93 cursor.execute( query)124 sq_name = util.truncate_name(table_name, get_max_name_length()-3) 125 cursor.execute('SELECT %s_sq.currval FROM dual' % sq_name) 94 126 return cursor.fetchone()[0] 95 127 96 128 def get_date_extract_sql(lookup_type, table_name): 97 129 # lookup_type is 'year', 'month', 'day' 98 # http:// www.psoug.org/reference/date_func.html130 # http://download-east.oracle.com/docs/cd/B10501_01/server.920/a96540/functions42a.htm#1017163 99 131 return "EXTRACT(%s FROM %s)" % (lookup_type, table_name) 100 132 101 133 def get_date_trunc_sql(lookup_type, field_name): 102 return "EXTRACT(%s FROM TRUNC(%s))" % (lookup_type, field_name) 134 # lookup_type is 'year', 'month', 'day' 135 # Oracle uses TRUNC() for both dates and numbers. 136 # http://download-east.oracle.com/docs/cd/B10501_01/server.920/a96540/functions155a.htm#SQLRF06151 137 if lookup_type == 'day': 138 sql = 'TRUNC(%s)' % (field_name,) 139 else: 140 sql = "TRUNC(%s, '%s')" % (field_name, lookup_type) 141 return sql 103 142 143 def get_datetime_cast_sql(): 144 return "TO_TIMESTAMP(%s, 'YYYY-MM-DD HH24:MI:SS')" 145 104 146 def get_limit_offset_sql(limit, offset=None): 105 147 # Limits and offset are too complicated to be handled here. 106 # Instead, they are handled in django/db/ query.py.107 pass148 # Instead, they are handled in django/db/backends/oracle/query.py. 149 return "" 108 150 109 151 def get_random_function_sql(): 110 152 return "DBMS_RANDOM.RANDOM" … … 116 158 raise NotImplementedError 117 159 118 160 def get_drop_foreignkey_sql(): 119 return "DROP FOREIGN KEY"161 return "DROP CONSTRAINT" 120 162 121 163 def get_pk_default_value(): 122 164 return "DEFAULT" 123 165 166 def get_max_name_length(): 167 return 30 168 169 def get_start_transaction_sql(): 170 return None 171 172 def get_tablespace_sql(tablespace, inline=False): 173 return "%sTABLESPACE %s" % ((inline and "USING INDEX " or ""), quote_name(tablespace)) 174 175 def get_autoinc_sql(table): 176 # To simulate auto-incrementing primary keys in Oracle, we have to 177 # create a sequence and a trigger. 178 sq_name = get_sequence_name(table) 179 tr_name = get_trigger_name(table) 180 sequence_sql = 'CREATE SEQUENCE %s;' % sq_name 181 trigger_sql = """CREATE OR REPLACE TRIGGER %s 182 BEFORE INSERT ON %s 183 FOR EACH ROW 184 WHEN (new.id IS NULL) 185 BEGIN 186 SELECT %s.nextval INTO :new.id FROM dual; 187 END;\n""" % (tr_name, quote_name(table), sq_name) 188 return sequence_sql, trigger_sql 189 190 def get_drop_sequence(table): 191 return "DROP SEQUENCE %s;" % quote_name(get_sequence_name(table)) 192 193 def _get_sequence_reset_sql(): 194 # TODO: colorize this SQL code with style.SQL_KEYWORD(), etc. 195 return """ 196 DECLARE 197 startvalue integer; 198 cval integer; 199 BEGIN 200 LOCK TABLE %(table)s IN SHARE MODE; 201 SELECT NVL(MAX(id), 0) INTO startvalue FROM %(table)s; 202 SELECT %(sequence)s.nextval INTO cval FROM dual; 203 cval := startvalue - cval; 204 IF cval != 0 THEN 205 EXECUTE IMMEDIATE 'ALTER SEQUENCE %(sequence)s MINVALUE 0 INCREMENT BY '||cval; 206 SELECT %(sequence)s.nextval INTO cval FROM dual; 207 EXECUTE IMMEDIATE 'ALTER SEQUENCE %(sequence)s INCREMENT BY 1'; 208 END IF; 209 COMMIT; 210 END;\n""" 211 124 212 def get_sql_flush(style, tables, sequences): 125 213 """Return a list of SQL statements required to remove all data from 126 214 all tables in the database (without actually removing the tables 127 215 themselves) and put the database in an empty 'initial' state 128 216 """ 129 # Return a list of 'TRUNCATE x;', 'TRUNCATE y;', 'TRUNCATE z;'... style SQL statements 130 # TODO - SQL not actually tested against Oracle yet! 131 # TODO - autoincrement indices reset required? See other get_sql_flush() implementations 132 sql = ['%s %s;' % \ 133 (style.SQL_KEYWORD('TRUNCATE'), 217 # Return a list of 'TRUNCATE x;', 'TRUNCATE y;', 218 # 'TRUNCATE z;'... style SQL statements 219 if tables: 220 # Oracle does support TRUNCATE, but it seems to get us into 221 # FK referential trouble, whereas DELETE FROM table works. 222 sql = ['%s %s %s;' % \ 223 (style.SQL_KEYWORD('DELETE'), 224 style.SQL_KEYWORD('FROM'), 134 225 style.SQL_FIELD(quote_name(table)) 135 226 ) for table in tables] 227 # Since we've just deleted all the rows, running our sequence 228 # ALTER code will reset the sequence to 0. 229 for sequence_info in sequences: 230 table_name = sequence_info['table'] 231 seq_name = get_sequence_name(table_name) 232 query = _get_sequence_reset_sql() % {'sequence':seq_name, 233 'table':quote_name(table_name)} 234 sql.append(query) 235 return sql 236 else: 237 return [] 136 238 239 def get_sequence_name(table): 240 name_length = get_max_name_length() - 3 241 return '%s_SQ' % util.truncate_name(table, name_length).upper() 242 137 243 def get_sql_sequence_reset(style, model_list): 138 244 "Returns a list of the SQL statements to reset sequences for the given models." 139 # No sequence reset required 140 return [] 245 from django.db import models 246 output = [] 247 query = _get_sequence_reset_sql() 248 for model in model_list: 249 for f in model._meta.fields: 250 if isinstance(f, models.AutoField): 251 sequence_name = get_sequence_name(model._meta.db_table) 252 output.append(query % {'sequence':sequence_name, 253 'table':model._meta.db_table}) 254 break # Only one AutoField is allowed per model, so don't bother continuing. 255 for f in model._meta.many_to_many: 256 sequence_name = get_sequence_name(f.m2m_db_table()) 257 output.append(query % {'sequence':sequence_name, 258 'table':f.m2m_db_table()}) 259 return output 141 260 261 def get_trigger_name(table): 262 name_length = get_max_name_length() - 3 263 return '%s_TR' % util.truncate_name(table, name_length).upper() 264 265 def get_query_set_class(DefaultQuerySet): 266 "Create a custom QuerySet class for Oracle." 267 268 from django.db import backend, connection 269 from django.db.models.query import EmptyResultSet, GET_ITERATOR_CHUNK_SIZE 270 271 class OracleQuerySet(DefaultQuerySet): 272 273 def iterator(self): 274 "Performs the SELECT database lookup of this QuerySet." 275 276 from django.db.models.query import get_cached_row 277 278 # self._select is a dictionary, and dictionaries' key order is 279 # undefined, so we convert it to a list of tuples. 280 extra_select = self._select.items() 281 282 full_query = None 283 284 try: 285 try: 286 select, sql, params, full_query = self._get_sql_clause(get_full_query=True) 287 except TypeError: 288 select, sql, params = self._get_sql_clause() 289 except EmptyResultSet: 290 raise StopIteration 291 if not full_query: 292 full_query = "SELECT %s%s\n%s" % \ 293 ((self._distinct and "DISTINCT " or ""), 294 ', '.join(select), sql) 295 296 cursor = connection.cursor() 297 cursor.execute(full_query, params) 298 299 fill_cache = self._select_related 300 fields = self.model._meta.fields 301 index_end = len(fields) 302 303 # so here's the logic; 304 # 1. retrieve each row in turn 305 # 2. convert NCLOBs 306 307 while 1: 308 rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE) 309 if not rows: 310 raise StopIteration 311 for row in rows: 312 row = self.resolve_columns(row, fields) 313 if fill_cache: 314 obj, index_end = get_cached_row(klass=self.model, row=row, 315 index_start=0, max_depth=self._max_related_depth) 316 else: 317 obj = self.model(*row[:index_end]) 318 for i, k in enumerate(extra_select): 319 setattr(obj, k[0], row[index_end+i]) 320 yield obj 321 322 323 def _get_sql_clause(self, get_full_query=False): 324 from django.db.models.query import fill_table_cache, \ 325 handle_legacy_orderlist, orderfield2column 326 327 opts = self.model._meta 328 329 # Construct the fundamental parts of the query: SELECT X FROM Y WHERE Z. 330 select = ["%s.%s" % (backend.quote_name(opts.db_table), backend.quote_name(f.column)) for f in opts.fields] 331 tables = [quote_only_if_word(t) for t in self._tables] 332 joins = SortedDict() 333 where = self._where[:] 334 params = self._params[:] 335 336 # Convert self._filters into SQL. 337 joins2, where2, params2 = self._filters.get_sql(opts) 338 joins.update(joins2) 339 where.extend(where2) 340 params.extend(params2) 341 342 # Add additional tables and WHERE clauses based on select_related. 343 if self._select_related: 344 fill_table_cache(opts, select, tables, where, opts.db_table, [opts.db_table]) 345 346 # Add any additional SELECTs. 347 if self._select: 348 select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in self._select.items()]) 349 350 # Start composing the body of the SQL statement. 351 sql = [" FROM", backend.quote_name(opts.db_table)] 352 353 # Compose the join dictionary into SQL describing the joins. 354 if joins: 355 sql.append(" ".join(["%s %s %s ON %s" % (join_type, table, alias, condition) 356 for (alias, (table, join_type, condition)) in joins.items()])) 357 358 # Compose the tables clause into SQL. 359 if tables: 360 sql.append(", " + ", ".join(tables)) 361 362 # Compose the where clause into SQL. 363 if where: 364 sql.append(where and "WHERE " + " AND ".join(where)) 365 366 # ORDER BY clause 367 order_by = [] 368 if self._order_by is not None: 369 ordering_to_use = self._order_by 370 else: 371 ordering_to_use = opts.ordering 372 for f in handle_legacy_orderlist(ordering_to_use): 373 if f == '?': # Special case. 374 order_by.append(backend.get_random_function_sql()) 375 else: 376 if f.startswith('-'): 377 col_name = f[1:] 378 order = "DESC" 379 else: 380 col_name = f 381 order = "ASC" 382 if "." in col_name: 383 table_prefix, col_name = col_name.split('.', 1) 384 table_prefix = backend.quote_name(table_prefix) + '.' 385 else: 386 # Use the database table as a column prefix if it wasn't given, 387 # and if the requested column isn't a custom SELECT. 388 if "." not in col_name and col_name not in (self._select or ()): 389 table_prefix = backend.quote_name(opts.db_table) + '.' 390 else: 391 table_prefix = '' 392 order_by.append('%s%s %s' % (table_prefix, backend.quote_name(orderfield2column(col_name, opts)), order)) 393 if order_by: 394 sql.append("ORDER BY " + ", ".join(order_by)) 395 396 # Look for column name collisions in the select elements 397 # and fix them with an AS alias. This allows us to do a 398 # SELECT * later in the paging query. 399 cols = [clause.split('.')[-1] for clause in select] 400 for index, col in enumerate(cols): 401 if cols.count(col) > 1: 402 col = '%s%d' % (col.replace('"', ''), index) 403 cols[index] = col 404 select[index] = '%s AS %s' % (select[index], col) 405 406 # LIMIT and OFFSET clauses 407 # To support limits and offsets, Oracle requires some funky rewriting of an otherwise normal looking query. 408 select_clause = ",".join(select) 409 distinct = (self._distinct and "DISTINCT " or "") 410 411 if order_by: 412 order_by_clause = " OVER (ORDER BY %s )" % (", ".join(order_by)) 413 else: 414 #Oracle's row_number() function always requires an order-by clause. 415 #So we need to define a default order-by, since none was provided. 416 order_by_clause = " OVER (ORDER BY %s.%s)" % \ 417 (backend.quote_name(opts.db_table), 418 backend.quote_name(opts.fields[0].db_column or opts.fields[0].column)) 419 # limit_and_offset_clause 420 if self._limit is None: 421 assert self._offset is None, "'offset' is not allowed without 'limit'" 422 423 if self._offset is not None: 424 offset = int(self._offset) 425 else: 426 offset = 0 427 if self._limit is not None: 428 limit = int(self._limit) 429 else: 430 limit = None 431 432 limit_and_offset_clause = '' 433 if limit is not None: 434 limit_and_offset_clause = "WHERE rn > %s AND rn <= %s" % (offset, limit+offset) 435 elif offset: 436 limit_and_offset_clause = "WHERE rn > %s" % (offset) 437 438 if len(limit_and_offset_clause) > 0: 439 fmt = \ 440 """SELECT * FROM 441 (SELECT %s%s, 442 ROW_NUMBER()%s AS rn 443 %s) 444 %s""" 445 full_query = fmt % (distinct, select_clause, 446 order_by_clause, ' '.join(sql).strip(), 447 limit_and_offset_clause) 448 else: 449 full_query = None 450 451 if get_full_query: 452 return select, " ".join(sql), params, full_query 453 else: 454 return select, " ".join(sql), params 455 456 def resolve_columns(self, row, fields=()): 457 from django.db.models.fields import DateField, DateTimeField, \ 458 TimeField, BooleanField, NullBooleanField 459 values = [] 460 for value, field in map(None, row, fields): 461 if isinstance(value, Database.LOB): 462 value = value.read() 463 # Since Oracle won't distinguish between NULL and an empty 464 # string (''), we store empty strings as a space. Here is 465 # where we undo that treachery. 466 if value == ' ': 467 value = '' 468 # Convert 1 or 0 to True or False 469 elif value in (1, 0) and isinstance(field, (BooleanField, NullBooleanField)): 470 value = bool(value) 471 # cx_Oracle always returns datetime.datetime objects for 472 # DATE and TIMESTAMP columns, but Django wants to see a 473 # python datetime.date, .time, or .datetime. We use the type 474 # of the Field to determine which to cast to, but it's not 475 # always available. 476 # As a workaround, we cast to date if all the time-related 477 # values are 0, or to time if the date is 1/1/1900. 478 # This could be cleaned a bit by adding a method to the Field 479 # classes to normalize values from the database (the to_python 480 # method is used for validation and isn't what we want here). 481 elif isinstance(value, Database.Timestamp): 482 # In Python 2.3, the cx_Oracle driver returns its own 483 # Timestamp object that we must convert to a datetime class. 484 if not isinstance(value, datetime.datetime): 485 value = datetime.datetime(value.year, value.month, value.day, value.hour, 486 value.minute, value.second, value.fsecond) 487 if isinstance(field, DateTimeField): 488 pass # DateTimeField subclasses DateField so must be checked first. 489 elif isinstance(field, DateField): 490 value = value.date() 491 elif isinstance(field, TimeField) or (value.year == 1900 and value.month == value.day == 1): 492 value = value.time() 493 elif value.hour == value.minute == value.second == value.microsecond == 0: 494 value = value.date() 495 values.append(value) 496 return values 497 498 return OracleQuerySet 499 500 142 501 OPERATOR_MAPPING = { 143 502 'exact': '= %s', 144 'iexact': ' LIKE %s',145 'contains': 'LIKE %s',146 'icontains': 'LIKE %s',503 'iexact': '= UPPER(%s)', 504 'contains': "LIKE %s ESCAPE '\\'", 505 'icontains': "LIKE UPPER(%s) ESCAPE '\\'", 147 506 'gt': '> %s', 148 507 'gte': '>= %s', 149 508 'lt': '< %s', 150 509 'lte': '<= %s', 151 'startswith': 'LIKE %s',152 'endswith': 'LIKE %s',153 'istartswith': 'LIKE %s',154 'iendswith': 'LIKE %s',510 'startswith': "LIKE %s ESCAPE '\\'", 511 'endswith': "LIKE %s ESCAPE '\\'", 512 'istartswith': "LIKE UPPER(%s) ESCAPE '\\'", 513 'iendswith': "LIKE UPPER(%s) ESCAPE '\\'", 155 514 } -
django/db/backends/oracle/client.py
2 2 import os 3 3 4 4 def runshell(): 5 args = '' 6 args += settings.DATABASE_USER 5 dsn = settings.DATABASE_USER 7 6 if settings.DATABASE_PASSWORD: 8 args += "/%s" % settings.DATABASE_PASSWORD 9 args += "@%s" % settings.DATABASE_NAME 10 os.execvp('sqlplus', args) 7 dsn += "/%s" % settings.DATABASE_PASSWORD 8 if settings.DATABASE_NAME: 9 dsn += "@%s" % settings.DATABASE_NAME 10 args = ["sqlplus", "-L", dsn] 11 os.execvp("sqlplus", args) -
django/db/backends/oracle/introspection.py
1 from django.db.backends.oracle.base import quote_name 1 2 import re 3 import cx_Oracle 2 4 5 3 6 foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)` \(`([^`]*)`\)") 4 7 5 8 def get_table_list(cursor): 6 9 "Returns a list of table names in the current database." 7 10 cursor.execute("SELECT TABLE_NAME FROM USER_TABLES") 8 return [row[0] for row in cursor.fetchall()]11 return [row[0].upper() for row in cursor.fetchall()] 9 12 10 13 def get_table_description(cursor, table_name): 11 return table_name 14 "Returns a description of the table, with the DB-API cursor.description interface." 15 cursor.execute("SELECT * FROM %s WHERE ROWNUM < 2" % quote_name(table_name)) 16 return cursor.description 12 17 13 18 def _name_to_index(cursor, table_name): 14 19 """ … … 22 27 Returns a dictionary of {field_index: (field_index_other_table, other_table)} 23 28 representing all relationships to the given table. Indexes are 0-based. 24 29 """ 25 raise NotImplementedError 30 cursor.execute(""" 31 SELECT ta.column_id - 1, tb.table_name, tb.column_id - 1 32 FROM user_constraints, USER_CONS_COLUMNS ca, USER_CONS_COLUMNS cb, 33 user_tab_cols ta, user_tab_cols tb 34 WHERE user_constraints.table_name = %s AND 35 ta.table_name = %s AND 36 ta.column_name = ca.column_name AND 37 ca.table_name = %s AND 38 user_constraints.constraint_name = ca.constraint_name AND 39 user_constraints.r_constraint_name = cb.constraint_name AND 40 cb.table_name = tb.table_name AND 41 cb.column_name = tb.column_name AND 42 ca.position = cb.position""", [table_name, table_name, table_name]) 26 43 44 relations = {} 45 for row in cursor.fetchall(): 46 relations[row[0]] = (row[2], row[1]) 47 return relations 48 27 49 def get_indexes(cursor, table_name): 28 50 """ 29 51 Returns a dictionary of fieldname -> infodict for the given table, … … 31 53 {'primary_key': boolean representing whether it's the primary key, 32 54 'unique': boolean representing whether it's a unique index} 33 55 """ 34 raise NotImplementedError 56 # This query retrieves each index on the given table, including the 57 # first associated field name 58 # "We were in the nick of time; you were in great peril!" 59 sql = """ 60 WITH primarycols AS ( 61 SELECT user_cons_columns.table_name, user_cons_columns.column_name, 1 AS PRIMARYCOL 62 FROM user_cons_columns, user_constraints 63 WHERE user_cons_columns.constraint_name = user_constraints.constraint_name AND 64 user_constraints.constraint_type = 'P' AND 65 user_cons_columns.table_name = %s), 66 uniquecols AS ( 67 SELECT user_ind_columns.table_name, user_ind_columns.column_name, 1 AS UNIQUECOL 68 FROM user_indexes, user_ind_columns 69 WHERE uniqueness = 'UNIQUE' AND 70 user_indexes.index_name = user_ind_columns.index_name AND 71 user_ind_columns.table_name = %s) 72 SELECT allcols.column_name, primarycols.primarycol, uniquecols.UNIQUECOL 73 FROM (SELECT column_name FROM primarycols UNION SELECT column_name FROM 74 uniquecols) allcols, 75 primarycols, uniquecols 76 WHERE allcols.column_name = primarycols.column_name (+) AND 77 allcols.column_name = uniquecols.column_name (+) 78 """ 79 cursor.execute(sql, [table_name, table_name]) 80 indexes = {} 81 for row in cursor.fetchall(): 82 # row[1] (idx.indkey) is stored in the DB as an array. It comes out as 83 # a string of space-separated integers. This designates the field 84 # indexes (1-based) of the fields that have indexes on the table. 85 # Here, we skip any indexes across multiple fields. 86 indexes[row[0]] = {'primary_key': row[1], 'unique': row[2]} 87 return indexes 35 88 36 # Maps type codes to Django Field types.89 # Maps type objects to Django Field types. 37 90 DATA_TYPES_REVERSE = { 38 16: 'BooleanField', 39 21: 'SmallIntegerField', 40 23: 'IntegerField', 41 25: 'TextField', 42 869: 'IPAddressField', 43 1043: 'CharField', 44 1082: 'DateField', 45 1083: 'TimeField', 46 1114: 'DateTimeField', 47 1184: 'DateTimeField', 48 1266: 'TimeField', 49 1700: 'FloatField', 91 cx_Oracle.CLOB: 'TextField', 92 cx_Oracle.DATETIME: 'DateTimeField', 93 cx_Oracle.FIXED_CHAR: 'CharField', 94 cx_Oracle.NCLOB: 'TextField', 95 cx_Oracle.NUMBER: 'FloatField', 96 cx_Oracle.STRING: 'TextField', 97 cx_Oracle.TIMESTAMP: 'DateTimeField', 50 98 } -
django/db/backends/oracle/creation.py
1 import sys, time 2 from django.core import management 3 4 # This dictionary maps Field objects to their associated Oracle column 5 # types, as strings. Column-type strings can contain format strings; they'll 6 # be interpolated against the values of Field.__dict__ before being output. 7 # If a column type is set to None, it won't be included in the output. 1 8 DATA_TYPES = { 2 'AutoField': 'number(38)',3 'BooleanField': 'number(1)',4 'CharField': 'varchar2(%(maxlength)s)',5 'CommaSeparatedIntegerField': 'varchar2(%(maxlength)s)',6 'DateField': 'date',7 'DateTimeField': 'date',8 'FileField': 'varchar2(100)',9 'FilePathField': 'varchar2(100)',10 'FloatField': 'number(%(max_digits)s, %(decimal_places)s)',11 'ImageField': 'varchar2(100)',12 'IntegerField': 'integer',13 'IPAddressField': 'char(15)',9 'AutoField': 'NUMBER(11)', 10 'BooleanField': 'NUMBER(1) CHECK (%(column)s IN (0,1))', 11 'CharField': 'VARCHAR2(%(maxlength)s)', 12 'CommaSeparatedIntegerField': 'VARCHAR2(%(maxlength)s)', 13 'DateField': 'DATE', 14 'DateTimeField': 'TIMESTAMP', 15 'FileField': 'VARCHAR2(100)', 16 'FilePathField': 'VARCHAR2(100)', 17 'FloatField': 'NUMBER(%(max_digits)s, %(decimal_places)s)', 18 'ImageField': 'VARCHAR2(100)', 19 'IntegerField': 'NUMBER(11)', 20 'IPAddressField': 'VARCHAR2(15)', 14 21 'ManyToManyField': None, 15 'NullBooleanField': 'integer', 16 'OneToOneField': 'integer', 17 'PhoneNumberField': 'varchar(20)', 18 'PositiveIntegerField': 'integer', 19 'PositiveSmallIntegerField': 'smallint', 20 'SlugField': 'varchar(50)', 21 'SmallIntegerField': 'smallint', 22 'TextField': 'long', 23 'TimeField': 'timestamp', 24 'USStateField': 'varchar(2)', 22 'NullBooleanField': 'NUMBER(1) CHECK ((%(column)s IN (0,1)) OR (%(column)s IS NULL))', 23 'OneToOneField': 'NUMBER(11)', 24 'PhoneNumberField': 'VARCHAR2(20)', 25 'PositiveIntegerField': 'NUMBER(11) CHECK (%(column)s >= 0)', 26 'PositiveSmallIntegerField': 'NUMBER(11) CHECK (%(column)s >= 0)', 27 'SlugField': 'VARCHAR2(50)', 28 'SmallIntegerField': 'NUMBER(11)', 29 'TextField': 'NCLOB', 30 'TimeField': 'TIMESTAMP', 31 'URLField': 'VARCHAR2(200)', 32 'USStateField': 'CHAR(2)', 25 33 } 34 35 TEST_DATABASE_PREFIX = 'test_' 36 PASSWORD = 'Im_a_lumberjack' 37 REMEMBER = {} 38 39 40 def create_test_db(settings, connection, backend, verbosity=1, autoclobber=False): 41 42 TEST_DATABASE_NAME = _test_database_name(settings) 43 TEST_DATABASE_USER = _test_database_user(settings) 44 TEST_DATABASE_PASSWD = _test_database_passwd(settings) 45 TEST_DATABASE_TBLSPACE = _test_database_tblspace(settings) 46 TEST_DATABASE_TBLSPACE_TMP = _test_database_tblspace_tmp(settings) 47 48 parameters = { 49 'dbname': TEST_DATABASE_NAME, 50 'user': TEST_DATABASE_USER, 51 'password': TEST_DATABASE_PASSWD, 52 'tblspace': TEST_DATABASE_TBLSPACE, 53 'tblspace_temp': TEST_DATABASE_TBLSPACE_TMP, 54 } 55 56 REMEMBER['user'] = settings.DATABASE_USER 57 REMEMBER['passwd'] = settings.DATABASE_PASSWORD 58 59 cursor = connection.cursor() 60 if _test_database_create(settings): 61 if verbosity >= 1: 62 print 'Creating test database...' 63 try: 64 _create_test_db(cursor, parameters, verbosity) 65 except Exception, e: 66 sys.stderr.write("Got an error creating the test database: %s\n" % e) 67 if not autoclobber: 68 confirm = raw_input("It appears the test database, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % TEST_DATABASE_NAME) 69 if autoclobber or confirm == 'yes': 70 try: 71 if verbosity >= 1: 72 print "Destroying old test database..." 73 _destroy_test_db(cursor, parameters, verbosity) 74 if verbosity >= 1: 75 print "Creating test database..." 76 _create_test_db(cursor, parameters, verbosity) 77 except Exception, e: 78 sys.stderr.write("Got an error recreating the test database: %s\n" % e) 79 sys.exit(2) 80 else: 81 print "Tests cancelled." 82 sys.exit(1) 83 84 if _test_user_create(settings): 85 if verbosity >= 1: 86 print "Creating test user..." 87 try: 88 _create_test_user(cursor, parameters, verbosity) 89 except Exception, e: 90 sys.stderr.write("Got an error creating the test user: %s\n" % e) 91 if not autoclobber: 92 confirm = raw_input("It appears the test user, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % TEST_DATABASE_USER) 93 if autoclobber or confirm == 'yes': 94 try: 95 if verbosity >= 1: 96 print "Destroying old test user..." 97 _destroy_test_user(cursor, parameters, verbosity) 98 if verbosity >= 1: 99 print "Creating test user..." 100 _create_test_user(cursor, parameters, verbosity) 101 except Exception, e: 102 sys.stderr.write("Got an error recreating the test user: %s\n" % e) 103 sys.exit(2) 104 else: 105 print "Tests cancelled." 106 sys.exit(1) 107 108 connection.close() 109 settings.DATABASE_USER = TEST_DATABASE_USER 110 settings.DATABASE_PASSWORD = TEST_DATABASE_PASSWD 111 112 management.syncdb(verbosity, interactive=False) 113 114 # Get a cursor (even though we don't need one yet). This has 115 # the side effect of initializing the test database. 116 cursor = connection.cursor() 117 118 119 def destroy_test_db(settings, connection, backend, old_database_name, verbosity=1): 120 connection.close() 121 122 TEST_DATABASE_NAME = _test_database_name(settings) 123 TEST_DATABASE_USER = _test_database_user(settings) 124 TEST_DATABASE_PASSWD = _test_database_passwd(settings) 125 TEST_DATABASE_TBLSPACE = _test_database_tblspace(settings) 126 TEST_DATABASE_TBLSPACE_TMP = _test_database_tblspace_tmp(settings) 127 128 settings.DATABASE_NAME = old_database_name 129 settings.DATABASE_USER = REMEMBER['user'] 130 settings.DATABASE_PASSWORD = REMEMBER['passwd'] 131 132 parameters = { 133 'dbname': TEST_DATABASE_NAME, 134 'user': TEST_DATABASE_USER, 135 'password': TEST_DATABASE_PASSWD, 136 'tblspace': TEST_DATABASE_TBLSPACE, 137 'tblspace_temp': TEST_DATABASE_TBLSPACE_TMP, 138 } 139 140 REMEMBER['user'] = settings.DATABASE_USER 141 REMEMBER['passwd'] = settings.DATABASE_PASSWORD 142 143 cursor = connection.cursor() 144 time.sleep(1) # To avoid "database is being accessed by other users" errors. 145 if _test_user_create(settings): 146 if verbosity >= 1: 147 print 'Destroying test user...' 148 _destroy_test_user(cursor, parameters, verbosity) 149 if _test_database_create(settings): 150 if verbosity >= 1: 151 print 'Destroying test database...' 152 _destroy_test_db(cursor, parameters, verbosity) 153 connection.close() 154 155 156 def _create_test_db(cursor, parameters, verbosity): 157 if verbosity >= 2: 158 print "_create_test_db(): dbname = %s" % parameters['dbname'] 159 statements = [ 160 """CREATE TABLESPACE %(tblspace)s 161 DATAFILE '%(tblspace)s.dbf' SIZE 20M 162 REUSE AUTOEXTEND ON NEXT 10M MAXSIZE 100M 163 """, 164 """CREATE TEMPORARY TABLESPACE %(tblspace_temp)s 165 TEMPFILE '%(tblspace_temp)s.dbf' SIZE 20M 166 REUSE AUTOEXTEND ON NEXT 10M MAXSIZE 100M 167 """, 168 ] 169 _execute_statements(cursor, statements, parameters, verbosity) 170 171 172 def _create_test_user(cursor, parameters, verbosity): 173 if verbosity >= 2: 174 print "_create_test_user(): username = %s" % parameters['user'] 175 statements = [ 176 """CREATE USER %(user)s 177 IDENTIFIED BY %(password)s 178 DEFAULT TABLESPACE %(tblspace)s 179 TEMPORARY TABLESPACE %(tblspace_temp)s 180 """, 181 """GRANT CONNECT, RESOURCE TO %(user)s""", 182 ] 183 _execute_statements(cursor, statements, parameters, verbosity) 184 185 186 def _destroy_test_db(cursor, parameters, verbosity): 187 if verbosity >= 2: 188 print "_destroy_test_db(): dbname=%s" % parameters['dbname'] 189 statements = [ 190 'DROP TABLESPACE %(tblspace)s INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS', 191 'DROP TABLESPACE %(tblspace_temp)s INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS', 192 ] 193 _execute_statements(cursor, statements, parameters, verbosity) 194 195 196 def _destroy_test_user(cursor, parameters, verbosity): 197 if verbosity >= 2: 198 print "_destroy_test_user(): user=%s" % parameters['user'] 199 print "Be patient. This can take some time..." 200 statements = [ 201 'DROP USER %(user)s CASCADE', 202 ] 203 _execute_statements(cursor, statements, parameters, verbosity) 204 205 206 def _execute_statements(cursor, statements, parameters, verbosity): 207 for template in statements: 208 stmt = template % parameters 209 if verbosity >= 2: 210 print stmt 211 try: 212 cursor.execute(stmt) 213 except Exception, err: 214 sys.stderr.write("Failed (%s)\n" % (err)) 215 raise 216 217 218 def _test_database_name(settings): 219 name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME 220 try: 221 if settings.TEST_DATABASE_NAME: 222 name = settings.TEST_DATABASE_NAME 223 except AttributeError: 224 pass 225 except: 226 raise 227 return name 228 229 230 def _test_database_create(settings): 231 name = True 232 try: 233 if settings.TEST_DATABASE_CREATE: 234 name = True 235 else: 236 name = False 237 except AttributeError: 238 pass 239 except: 240 raise 241 return name 242 243 244 def _test_user_create(settings): 245 name = True 246 try: 247 if settings.TEST_USER_CREATE: 248 name = True 249 else: 250 name = False 251 except AttributeError: 252 pass 253 except: 254 raise 255 return name 256 257 258 def _test_database_user(settings): 259 name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME 260 try: 261 if settings.TEST_DATABASE_USER: 262 name = settings.TEST_DATABASE_USER 263 except AttributeError: 264 pass 265 except: 266 raise 267 return name 268 269 270 def _test_database_passwd(settings): 271 name = PASSWORD 272 try: 273 if settings.TEST_DATABASE_PASSWD: 274 name = settings.TEST_DATABASE_PASSWD 275 except AttributeError: 276 pass 277 except: 278 raise 279 return name 280 281 282 def _test_database_tblspace(settings): 283 name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME 284 try: 285 if settings.TEST_DATABASE_TBLSPACE: 286 name = settings.TEST_DATABASE_TBLSPACE 287 except AttributeError: 288 pass 289 except: 290 raise 291 return name 292 293 294 def _test_database_tblspace_tmp(settings): 295 name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME + '_temp' 296 try: 297 if settings.TEST_DATABASE_TBLSPACE_TMP: 298 name = settings.TEST_DATABASE_TBLSPACE_TMP 299 except AttributeError: 300 pass 301 except: 302 raise 303 return name -
django/db/backends/postgresql_psycopg2/base.py
72 72 self.connection.close() 73 73 self.connection = None 74 74 75 allows_group_by_ordinal = True 76 allows_unique_and_pk = True 77 autoindexes_primary_keys = True 78 needs_datetime_string_cast = False 79 needs_upper_for_iops = False 75 80 supports_constraints = True 81 supports_tablespaces = False 82 uses_case_insensitive_names = True 76 83 77 84 def quote_name(name): 78 85 if name.startswith('"') and name.endswith('"'): … … 97 104 # http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC 98 105 return "DATE_TRUNC('%s', %s)" % (lookup_type, field_name) 99 106 107 def get_datetime_cast_sql(): 108 return None 109 100 110 def get_limit_offset_sql(limit, offset=None): 101 111 sql = "LIMIT %s" % limit 102 112 if offset and offset != 0: … … 118 128 def get_pk_default_value(): 119 129 return "DEFAULT" 120 130 131 def get_max_name_length(): 132 return None 133 134 def get_start_transaction_sql(): 135 return "BEGIN;" 136 137 def get_autoinc_sql(table): 138 return None 139 121 140 def get_sql_flush(style, tables, sequences): 122 141 """Return a list of SQL statements required to remove all data from 123 142 all tables in the database (without actually removing the tables -
django/db/backends/dummy/base.py
27 27 pass # close() 28 28 29 29 supports_constraints = False 30 supports_tablespaces = False 30 31 quote_name = complain 31 32 dictfetchone = complain 32 33 dictfetchmany = complain -
django/db/models/base.py
210 210 record_exists = True 211 211 if pk_set: 212 212 # Determine whether a record with the primary key already exists. 213 cursor.execute("SELECT 1 FROM %s WHERE %s=%%s LIMIT 1" % \213 cursor.execute("SELECT COUNT(*) FROM %s WHERE %s=%%s" % \ 214 214 (backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column)), [pk_val]) 215 215 # If it does already exist, do an UPDATE. 216 if cursor.fetchone() :216 if cursor.fetchone()[0] > 0: 217 217 db_values = [f.get_db_prep_save(f.pre_save(self, False)) for f in non_pks] 218 218 if db_values: 219 219 cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \ -
django/db/models/options.py
13 13 14 14 DEFAULT_NAMES = ('verbose_name', 'db_table', 'ordering', 15 15 'unique_together', 'permissions', 'get_latest_by', 16 'order_with_respect_to', 'app_label' )16 'order_with_respect_to', 'app_label', 'db_tablespace') 17 17 18 18 class Options(object): 19 19 def __init__(self, meta): … … 27 27 self.object_name, self.app_label = None, None 28 28 self.get_latest_by = None 29 29 self.order_with_respect_to = None 30 self.db_tablespace = None 30 31 self.admin = None 31 32 self.meta = meta 32 33 self.pk = None … … 59 60 del self.meta 60 61 61 62 def _prepare(self, model): 63 from django.db import backend 64 from django.db.backends.util import truncate_name 62 65 if self.order_with_respect_to: 63 66 self.order_with_respect_to = self.get_field(self.order_with_respect_to) 64 67 self.ordering = ('_order',) … … 73 76 # If the db_table wasn't provided, use the app_label + module_name. 74 77 if not self.db_table: 75 78 self.db_table = "%s_%s" % (self.app_label, self.module_name) 79 self.db_table = truncate_name(self.db_table, 80 backend.get_max_name_length()) 76 81 77 82 def add_field(self, field): 78 83 # Insert the given field in the order in which it was created, using -
django/db/models/fields/__init__.py
70 70 core=False, rel=None, default=NOT_PROVIDED, editable=True, serialize=True, 71 71 prepopulate_from=None, unique_for_date=None, unique_for_month=None, 72 72 unique_for_year=None, validator_list=None, choices=None, radio_admin=None, 73 help_text='', db_column=None ):73 help_text='', db_column=None, db_tablespace=None): 74 74 self.name = name 75 75 self.verbose_name = verbose_name 76 76 self.primary_key = primary_key … … 87 87 self.radio_admin = radio_admin 88 88 self.help_text = help_text 89 89 self.db_column = db_column 90 self.db_tablespace = db_tablespace 90 91 91 92 # Set db_index to True if the field has a relationship and doesn't explicitly set db_index. 92 93 self.db_index = db_index … … 161 162 162 163 def get_db_prep_save(self, value): 163 164 "Returns field's value prepared for saving into a database." 165 # Oracle treats empty strings ('') the same as NULLs. 166 # To get around this wart, we need to change it to something else... 167 if settings.DATABASE_ENGINE == 'oracle' and value == '': 168 value = ' ' 164 169 return value 165 170 166 171 def get_db_prep_lookup(self, lookup_type, value): … … 528 533 def get_db_prep_save(self, value): 529 534 # Casts dates into string format for entry into database. 530 535 if value is not None: 531 # MySQL will throw a warning if microseconds are given, because it532 # doesn't supportmicroseconds.533 if settings.DATABASE_ENGINE == 'mysql'and hasattr(value, 'microsecond'):536 # MySQL/Oracle will throw a warning if microseconds are given, because 537 # neither database supports microseconds. 538 if settings.DATABASE_ENGINE in ('mysql', 'oracle') and hasattr(value, 'microsecond'): 534 539 value = value.replace(microsecond=0) 535 540 value = str(value) 536 541 return Field.get_db_prep_save(self, value) 537 542 538 543 def get_db_prep_lookup(self, lookup_type, value): 544 # Oracle will throw an error if microseconds are given, because it 545 # doesn't support microseconds. 546 if settings.DATABASE_ENGINE == 'oracle' and hasattr(value, 'microsecond'): 547 value = value.replace(microsecond=0) 539 548 if lookup_type == 'range': 540 549 value = [str(v) for v in value] 541 550 else: … … 808 817 Field.__init__(self, verbose_name, name, **kwargs) 809 818 810 819 def get_db_prep_lookup(self, lookup_type, value): 820 if settings.DATABASE_ENGINE == 'oracle': 821 # Oracle requires a date in order to parse. 822 def prep(value): 823 if isinstance(value, datetime.time): 824 value = datetime.datetime.combine(datetime.date(1900, 1, 1), value) 825 return str(value) 826 else: 827 prep = str 811 828 if lookup_type == 'range': 812 value = [ str(v) for v in value]829 value = [prep(v) for v in value] 813 830 else: 814 value = str(value)831 value = prep(value) 815 832 return Field.get_db_prep_lookup(self, lookup_type, value) 816 833 817 834 def pre_save(self, model_instance, add): … … 827 844 if value is not None: 828 845 # MySQL will throw a warning if microseconds are given, because it 829 846 # doesn't support microseconds. 830 if settings.DATABASE_ENGINE == 'mysql'and hasattr(value, 'microsecond'):847 if settings.DATABASE_ENGINE in ('mysql', 'oracle') and hasattr(value, 'microsecond'): 831 848 value = value.replace(microsecond=0) 849 if settings.DATABASE_ENGINE == 'oracle': 850 # cx_Oracle expects a datetime.datetime to persist into TIMESTAMP field. 851 if isinstance(value, datetime.time): 852 value = datetime.datetime(1900, 1, 1, value.hour, value.minute, value.second) 853 elif isinstance(value, basestring): 854 value = datetime.datetime(*(time.strptime(value, '%H:%M:%S')[:6])) 855 else: 832 856 value = str(value) 833 857 return Field.get_db_prep_save(self, value) 834 858 -
django/db/models/fields/related.py
335 335 (target_col_name, self.join_table, source_col_name, 336 336 target_col_name, ",".join(['%s'] * len(new_ids))), 337 337 [self._pk_val] + list(new_ids)) 338 if cursor.rowcount is not None and cursor.rowcount != 0: 339 existing_ids = set([row[0] for row in cursor.fetchmany(cursor.rowcount)]) 340 else: 341 existing_ids = set() 338 existing_ids = set([row[0] for row in cursor.fetchall()]) 342 339 343 340 # Add the ones that aren't there already 344 341 for obj_id in (new_ids - existing_ids): -
django/db/models/query.py
4 4 from django.db.models import signals 5 5 from django.dispatch import dispatcher 6 6 from django.utils.datastructures import SortedDict 7 from django.conf import settings 8 import datetime 7 9 import operator 8 10 import re 9 11 … … 77 79 else: 78 80 return backend.quote_name(word) 79 81 80 class QuerySet(object):82 class _QuerySet(object): 81 83 "Represents a lazy database lookup for a set of objects" 82 84 def __init__(self, model=None): 83 85 self.model = model … … 181 183 182 184 cursor = connection.cursor() 183 185 cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 186 184 187 fill_cache = self._select_related 185 index_end = len(self.model._meta.fields) 188 fields = self.model._meta.fields 189 index_end = len(fields) 190 has_resolve_columns = hasattr(self, 'resolve_columns') 186 191 while 1: 187 192 rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE) 188 193 if not rows: 189 194 raise StopIteration 190 195 for row in rows: 196 if has_resolve_columns: 197 row = self.resolve_columns(row, fields) 191 198 if fill_cache: 192 199 obj, index_end = get_cached_row(klass=self.model, row=row, 193 200 index_start=0, max_depth=self._max_related_depth) … … 551 558 552 559 return select, " ".join(sql), params 553 560 561 # Use the backend's QuerySet class if it defines one, otherwise use _QuerySet. 562 if hasattr(backend, 'get_query_set_class'): 563 QuerySet = backend.get_query_set_class(_QuerySet) 564 else: 565 QuerySet = _QuerySet 566 554 567 class ValuesQuerySet(QuerySet): 555 568 def __init__(self, *args, **kwargs): 556 569 super(ValuesQuerySet, self).__init__(*args, **kwargs) … … 566 579 567 580 # self._fields is a list of field names to fetch. 568 581 if self._fields: 569 columns = [self.model._meta.get_field(f, many_to_many=False).column for f in self._fields] 570 field_names = self._fields 582 fields = [self.model._meta.get_field(f, many_to_many=False) for f in self._fields] 571 583 else: # Default to all fields. 572 columns = [f.column for f in self.model._meta.fields] 573 field_names = [f.attname for f in self.model._meta.fields] 584 fields = self.model._meta.fields 585 columns = [f.column for f in fields] 586 field_names = [f.attname for f in fields] 574 587 575 588 select = ['%s.%s' % (backend.quote_name(self.model._meta.db_table), backend.quote_name(c)) for c in columns] 576 589 cursor = connection.cursor() 577 590 cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 591 592 has_resolve_columns = hasattr(self, 'resolve_columns') 578 593 while 1: 579 594 rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE) 580 595 if not rows: 581 596 raise StopIteration 582 597 for row in rows: 598 if has_resolve_columns: 599 row = self.resolve_columns(row, fields) 583 600 yield dict(zip(field_names, row)) 584 601 585 602 def _clone(self, klass=None, **kwargs): … … 590 607 class DateQuerySet(QuerySet): 591 608 def iterator(self): 592 609 from django.db.backends.util import typecast_timestamp 610 from django.db.models.fields import DateTimeField 593 611 self._order_by = () # Clear this because it'll mess things up otherwise. 594 612 if self._field.null: 595 613 self._where.append('%s.%s IS NOT NULL' % \ 596 614 (backend.quote_name(self.model._meta.db_table), backend.quote_name(self._field.column))) 597 598 615 try: 599 616 select, sql, params = self._get_sql_clause() 600 617 except EmptyResultSet: 601 618 raise StopIteration 602 619 603 sql = 'SELECT %s %s GROUP BY 1 ORDER BY 1 %s' % \ 620 table_name = backend.quote_name(self.model._meta.db_table) 621 field_name = backend.quote_name(self._field.column) 622 623 if backend.allows_group_by_ordinal: 624 group_by = '1' 625 else: 626 group_by = backend.get_date_trunc_sql(self._kind, 627 '%s.%s' % (table_name, field_name)) 628 629 sql = 'SELECT %s %s GROUP BY %s ORDER BY 1 %s' % \ 604 630 (backend.get_date_trunc_sql(self._kind, '%s.%s' % (backend.quote_name(self.model._meta.db_table), 605 backend.quote_name(self._field.column))), sql, self._order)631 backend.quote_name(self._field.column))), sql, group_by, self._order) 606 632 cursor = connection.cursor() 607 633 cursor.execute(sql, params) 608 # We have to manually run typecast_timestamp(str()) on the results, because609 # MySQL doesn't automatically cast the result of date functions as datetime610 # objects -- MySQL returns the values as strings, instead.611 return [typecast_timestamp(str(row[0])) for row in cursor.fetchall()]612 634 635 has_resolve_columns = hasattr(self, 'resolve_columns') 636 needs_datetime_string_cast = backend.needs_datetime_string_cast 637 dates = [] 638 # It would be better to use self._field here instead of DateTimeField(), 639 # but in Oracle that will result in a list of datetime.date instead of 640 # datetime.datetime. 641 fields = [DateTimeField()] 642 while 1: 643 rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE) 644 if not rows: 645 return dates 646 for row in rows: 647 date = row[0] 648 if has_resolve_columns: 649 date = self.resolve_columns([date], fields)[0] 650 elif needs_datetime_string_cast: 651 date = typecast_timestamp(str(date)) 652 dates.append(date) 653 613 654 def _clone(self, klass=None, **kwargs): 614 655 c = super(DateQuerySet, self)._clone(klass, **kwargs) 615 656 c._field = self._field … … 716 757 if table_prefix.endswith('.'): 717 758 table_prefix = backend.quote_name(table_prefix[:-1])+'.' 718 759 field_name = backend.quote_name(field_name) 760 if type(value) == datetime.datetime and backend.get_datetime_cast_sql(): 761 cast_sql = backend.get_datetime_cast_sql() 762 else: 763 cast_sql = '%s' 764 if lookup_type in ('iexact', 'icontains', 'istartswith', 'iendswith') and backend.needs_upper_for_iops: 765 format = 'UPPER(%s%s) %s' 766 else: 767 format = '%s%s %s' 719 768 try: 720 return '%s%s %s' % (table_prefix, field_name, (backend.OPERATOR_MAPPING[lookup_type] % '%s')) 769 return format % (table_prefix, field_name, 770 backend.OPERATOR_MAPPING[lookup_type] % cast_sql) 721 771 except KeyError: 722 772 pass 723 773 if lookup_type == 'in': -
django/core/management.py
55 55 56 56 def _get_installed_models(table_list): 57 57 "Gets a set of all models that are installed, given a list of existing tables" 58 from django.db import models58 from django.db import backend, models 59 59 all_models = [] 60 60 for app in models.get_apps(): 61 61 for model in models.get_models(app): 62 62 all_models.append(model) 63 return set([m for m in all_models if m._meta.db_table in table_list]) 63 if backend.uses_case_insensitive_names: 64 converter = str.upper 65 else: 66 converter = lambda x: x 67 return set([m for m in all_models if converter(m._meta.db_table) in map(converter, table_list)]) 64 68 65 69 def _get_table_list(): 66 70 "Gets a list of all db tables that are physically installed." … … 104 108 def get_sql_create(app): 105 109 "Returns a list of the CREATE TABLE SQL statements for the given app." 106 110 from django.db import get_creation_module, models 111 107 112 data_types = get_creation_module().DATA_TYPES 108 113 109 114 if not data_types: … … 173 178 rel_field = f 174 179 data_type = f.get_internal_type() 175 180 col_type = data_types[data_type] 181 tablespace = f.db_tablespace or opts.db_tablespace 176 182 if col_type is not None: 177 183 # Make the definition (e.g. 'foo VARCHAR(30)') for this field. 178 184 field_output = [style.SQL_FIELD(backend.quote_name(f.column)), 179 185 style.SQL_COLTYPE(col_type % rel_field.__dict__)] 180 186 field_output.append(style.SQL_KEYWORD('%sNULL' % (not f.null and 'NOT ' or ''))) 181 if f.unique :187 if f.unique and (not f.primary_key or backend.allows_unique_and_pk): 182 188 field_output.append(style.SQL_KEYWORD('UNIQUE')) 183 189 if f.primary_key: 184 190 field_output.append(style.SQL_KEYWORD('PRIMARY KEY')) 191 if tablespace and backend.supports_tablespaces and (f.unique or f.primary_key) and backend.autoindexes_primary_keys: 192 # We must specify the index tablespace inline, because we 193 # won't be generating a CREATE INDEX statement for this field. 194 field_output.append(backend.get_tablespace_sql(tablespace, inline=True)) 185 195 if f.rel: 186 196 if f.rel.to in known_models: 187 197 field_output.append(style.SQL_KEYWORD('REFERENCES') + ' ' + \ … … 205 215 full_statement = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + style.SQL_TABLE(backend.quote_name(opts.db_table)) + ' ('] 206 216 for i, line in enumerate(table_output): # Combine and add commas. 207 217 full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or '')) 208 full_statement.append(');') 218 full_statement.append(')') 219 if opts.db_tablespace and backend.supports_tablespaces: 220 full_statement.append(backend.get_tablespace_sql(opts.db_tablespace)) 221 full_statement.append(';') 209 222 final_output.append('\n'.join(full_statement)) 210 223 224 if opts.has_auto_field and hasattr(backend, 'get_autoinc_sql'): 225 # Add any extra SQL needed to support auto-incrementing primary keys 226 autoinc_sql = backend.get_autoinc_sql(opts.db_table) 227 if autoinc_sql: 228 for stmt in autoinc_sql: 229 final_output.append(stmt) 230 211 231 return final_output, pending_references 212 232 213 233 def _get_sql_for_pending_references(model, pending_references): … … 215 235 Get any ALTER TABLE statements to add constraints after the fact. 216 236 """ 217 237 from django.db import backend, get_creation_module 238 from django.db.backends.util import truncate_name 218 239 data_types = get_creation_module().DATA_TYPES 219 240 220 241 final_output = [] … … 227 248 r_col = f.column 228 249 table = opts.db_table 229 250 col = opts.get_field(f.rel.field_name).column 230 # For MySQL, r_name must be unique in the first 64 characters. 231 # So we are careful with character usage here. 232 r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table)))) 251 r_name = '%s_refs_%s_%s_%s' % (r_col, col, r_table, table) 233 252 final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % \ 234 (backend.quote_name(r_table), r_name,253 (backend.quote_name(r_table), truncate_name(r_name, backend.get_max_name_length()), 235 254 backend.quote_name(r_col), backend.quote_name(table), backend.quote_name(col), 236 255 backend.get_deferrable_sql())) 237 256 del pending_references[model] … … 247 266 final_output = [] 248 267 for f in opts.many_to_many: 249 268 if not isinstance(f.rel, GenericRel): 269 tablespace = f.db_tablespace or opts.db_tablespace 270 if tablespace and backend.supports_tablespaces and backend.autoindexes_primary_keys: 271 tablespace_sql = ' ' + backend.get_tablespace_sql(tablespace, inline=True) 272 else: 273 tablespace_sql = '' 250 274 table_output = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + \ 251 275 style.SQL_TABLE(backend.quote_name(f.m2m_db_table())) + ' ('] 252 table_output.append(' %s %s %s ,' % \276 table_output.append(' %s %s %s%s,' % \ 253 277 (style.SQL_FIELD(backend.quote_name('id')), 254 278 style.SQL_COLTYPE(data_types['AutoField']), 255 style.SQL_KEYWORD('NOT NULL PRIMARY KEY'))) 279 style.SQL_KEYWORD('NOT NULL PRIMARY KEY'), 280 tablespace_sql)) 256 281 table_output.append(' %s %s %s %s (%s)%s,' % \ 257 282 (style.SQL_FIELD(backend.quote_name(f.m2m_column_name())), 258 283 style.SQL_COLTYPE(data_types[get_rel_data_type(opts.pk)] % opts.pk.__dict__), … … 267 292 style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)), 268 293 style.SQL_FIELD(backend.quote_name(f.rel.to._meta.pk.column)), 269 294 backend.get_deferrable_sql())) 270 table_output.append(' %s (%s, %s) ' % \295 table_output.append(' %s (%s, %s)%s' % \ 271 296 (style.SQL_KEYWORD('UNIQUE'), 272 297 style.SQL_FIELD(backend.quote_name(f.m2m_column_name())), 273 style.SQL_FIELD(backend.quote_name(f.m2m_reverse_name())))) 274 table_output.append(');') 298 style.SQL_FIELD(backend.quote_name(f.m2m_reverse_name())), 299 tablespace_sql)) 300 table_output.append(')') 301 if opts.db_tablespace and backend.supports_tablespaces: 302 # f.db_tablespace is only for indices, so ignore its value here. 303 table_output.append(backend.get_tablespace_sql(opts.db_tablespace)) 304 table_output.append(';') 275 305 final_output.append('\n'.join(table_output)) 306 307 # Add any extra SQL needed to support auto-incrementing PKs 308 autoinc_sql = backend.get_autoinc_sql(f.m2m_db_table()) 309 if autoinc_sql: 310 for stmt in autoinc_sql: 311 final_output.append(stmt) 312 276 313 return final_output 277 314 278 315 def get_sql_delete(app): 279 316 "Returns a list of the DROP TABLE SQL statements for the given app." 280 317 from django.db import backend, connection, models, get_introspection_module 318 from django.db.backends.util import truncate_name 281 319 introspection = get_introspection_module() 282 320 283 321 # This should work even if a connection isn't available … … 291 329 table_names = introspection.get_table_list(cursor) 292 330 else: 293 331 table_names = [] 332 if backend.uses_case_insensitive_names: 333 table_name_converter = str.upper 334 else: 335 table_name_converter = lambda x: x 294 336 295 337 output = [] 296 338 … … 300 342 references_to_delete = {} 301 343 app_models = models.get_models(app) 302 344 for model in app_models: 303 if cursor and model._meta.db_tablein table_names:345 if cursor and table_name_converter(model._meta.db_table) in table_names: 304 346 # The table exists, so it needs to be dropped 305 347 opts = model._meta 306 348 for f in opts.fields: … … 310 352 to_delete.add(model) 311 353 312 354 for model in app_models: 313 if cursor and model._meta.db_tablein table_names:355 if cursor and table_name_converter(model._meta.db_table) in table_names: 314 356 # Drop the table now 315 357 output.append('%s %s;' % (style.SQL_KEYWORD('DROP TABLE'), 316 358 style.SQL_TABLE(backend.quote_name(model._meta.db_table)))) … … 320 362 col = f.column 321 363 r_table = model._meta.db_table 322 364 r_col = model._meta.get_field(f.rel.field_name).column 365 r_name = '%s_refs_%s_%s_%s' % (col, r_col, table, r_table) 323 366 output.append('%s %s %s %s;' % \ 324 367 (style.SQL_KEYWORD('ALTER TABLE'), 325 368 style.SQL_TABLE(backend.quote_name(table)), 326 369 style.SQL_KEYWORD(backend.get_drop_foreignkey_sql()), 327 style.SQL_FIELD( backend.quote_name('%s_refs_%s_%x' % (col, r_col, abs(hash((table, r_table))))))))370 style.SQL_FIELD(truncate_name(r_name, backend.get_max_name_length())))) 328 371 del references_to_delete[model] 372 if hasattr(backend, 'get_drop_sequence'): 373 output.append(backend.get_drop_sequence(model._meta.db_table)) 329 374 330 375 # Output DROP TABLE statements for many-to-many tables. 331 376 for model in app_models: 332 377 opts = model._meta 333 378 for f in opts.many_to_many: 334 if cursor and f.m2m_db_table() in table_names:379 if cursor and table_name_converter(f.m2m_db_table()) in table_names: 335 380 output.append("%s %s;" % (style.SQL_KEYWORD('DROP TABLE'), 336 381 style.SQL_TABLE(backend.quote_name(f.m2m_db_table())))) 382 if hasattr(backend, 'get_drop_sequence'): 383 output.append(backend.get_drop_sequence("%s_%s" % (model._meta.db_table, f.column))) 337 384 385 338 386 app_label = app_models[0]._meta.app_label 339 387 340 388 # Close database connection explicitly, in case this output is being piped … … 429 477 def get_sql_indexes_for_model(model): 430 478 "Returns the CREATE INDEX SQL statements for a single model" 431 479 from django.db import backend 480 from django.db.backends.util import truncate_name 432 481 output = [] 433 482 434 483 for f in model._meta.fields: 435 if f.db_index :484 if f.db_index and not ((f.primary_key or f.unique) and backend.autoindexes_primary_keys): 436 485 unique = f.unique and 'UNIQUE ' or '' 486 tablespace = f.db_tablespace or model._meta.db_tablespace 487 if tablespace and backend.supports_tablespaces: 488 tablespace_sql = ' ' + backend.get_tablespace_sql(tablespace) 489 else: 490 tablespace_sql = '' 437 491 output.append( 438 492 style.SQL_KEYWORD('CREATE %sINDEX' % unique) + ' ' + \ 439 493 style.SQL_TABLE(backend.quote_name('%s_%s' % (model._meta.db_table, f.column))) + ' ' + \ 440 494 style.SQL_KEYWORD('ON') + ' ' + \ 441 495 style.SQL_TABLE(backend.quote_name(model._meta.db_table)) + ' ' + \ 442 "(%s);" % style.SQL_FIELD(backend.quote_name(f.column)) 496 "(%s)" % style.SQL_FIELD(backend.quote_name(f.column)) + \ 497 "%s;" % tablespace_sql 443 498 ) 444 499 return output 445 500 … … 463 518 464 519 def syncdb(verbosity=1, interactive=True): 465 520 "Creates the database tables for all apps in INSTALLED_APPS whose tables haven't already been created." 466 from django.db import connection, transaction, models, get_creation_module521 from django.db import backend, connection, transaction, models, get_creation_module 467 522 from django.conf import settings 468 523 469 524 disable_termcolors() … … 486 541 # Get a list of all existing database tables, 487 542 # so we know what needs to be added. 488 543 table_list = _get_table_list() 544 if backend.uses_case_insensitive_names: 545 table_name_converter = str.upper 546 else: 547 table_name_converter = lambda x: x 489 548 490 549 # Get a list of already installed *models* so that references work right. 491 550 seen_models = _get_installed_models(table_list) … … 500 559 # Create the model's database table, if it doesn't already exist. 501 560 if verbosity >= 2: 502 561 print "Processing %s.%s model" % (app_name, model._meta.object_name) 503 if model._meta.db_tablein table_list:562 if table_name_converter(model._meta.db_table) in table_list: 504 563 continue 505 564 sql, references = _get_sql_model_create(model, seen_models) 506 565 seen_models.add(model) … … 512 571 print "Creating table %s" % model._meta.db_table 513 572 for statement in sql: 514 573 cursor.execute(statement) 515 table_list.append( model._meta.db_table)574 table_list.append(table_name_converter(model._meta.db_table)) 516 575 517 576 # Create the m2m tables. This must be done after all tables have been created 518 577 # to ensure that all referred tables will exist. … … 830 889 except NotImplementedError: 831 890 indexes = {} 832 891 for i, row in enumerate(introspection_module.get_table_description(cursor, table_name)): 833 att_name = row[0] 892 att_name = row[0].lower() 834 893 comment_notes = [] # Holds Field notes, to be displayed in a Python comment. 835 894 extra_params = {} # Holds Field parameters such as 'db_column'. 836 895 … … 1621 1680 if not mod_list: 1622 1681 parser.print_usage_and_exit() 1623 1682 if action not in NO_SQL_TRANSACTION: 1624 print style.SQL_KEYWORD("BEGIN;") 1683 from django.db import backend 1684 if backend.get_start_transaction_sql(): 1685 print style.SQL_KEYWORD(backend.get_start_transaction_sql()) 1625 1686 for mod in mod_list: 1626 1687 if action == 'reset': 1627 1688 output = action_mapping[action](mod, options.interactive) -
django/contrib/admin/models.py
9 9 10 10 class LogEntryManager(models.Manager): 11 11 def log_action(self, user_id, content_type_id, object_id, object_repr, action_flag, change_message=''): 12 e = self.model(None, None, user_id, content_type_id, object_id, object_repr[:200], action_flag, change_message)12 e = self.model(None, None, user_id, content_type_id, str(object_id), object_repr[:200], action_flag, change_message) 13 13 e.save() 14 14 15 15 class LogEntry(models.Model): -
django/test/utils.py
1 1 import sys, time 2 2 from django.conf import settings 3 from django.db import connection, transaction, backend3 from django.db import connection, backend, get_creation_module 4 4 from django.core import management 5 5 from django.dispatch import dispatcher 6 6 from django.test import signals … … 44 44 connection.connection.set_isolation_level(0) 45 45 46 46 def create_test_db(verbosity=1, autoclobber=False): 47 # If the database backend wants to create the test DB itself, let it 48 creation_module = get_creation_module() 49 if hasattr(creation_module, "create_test_db"): 50 creation_module.create_test_db(settings, connection, backend, verbosity, autoclobber) 51 return 52 47 53 if verbosity >= 1: 48 54 print "Creating test database..." 49 55 # If we're using SQLite, it's more convenient to test against an … … 92 98 cursor = connection.cursor() 93 99 94 100 def destroy_test_db(old_database_name, verbosity=1): 101 # If the database wants to drop the test DB itself, let it 102 creation_module = get_creation_module() 103 if hasattr(creation_module, "destroy_test_db"): 104 creation_module.destroy_test_db(settings, connection, backend, old_database_name, verbosity) 105 return 106 95 107 # Unless we're using SQLite, remove the test database to clean up after 96 108 # ourselves. Connect to the previous database (not the test database) 97 109 # to do so, because it's not allowed to delete a database while being -
docs/settings.txt
245 245 Default: ``''`` (Empty string) 246 246 247 247 Which database backend to use. Either ``'postgresql_psycopg2'``, 248 ``'postgresql'``, ``'mysql'``, ``'mysql_old'``, ``'sqlite3'`` or249 ``' ado_mssql'``.248 ``'postgresql'``, ``'mysql'``, ``'mysql_old'``, ``'sqlite3'``, 249 ``'oracle'``, or ``'ado_mssql'``. 250 250 251 251 DATABASE_HOST 252 252 ------------- -
docs/faq.txt
301 301 302 302 If you want to use Django with a database, which is probably the case, you'll 303 303 also need a database engine. PostgreSQL_ is recommended, because we're 304 PostgreSQL fans, and MySQL_ and `SQLite 3`_ are also supported.304 PostgreSQL fans, and MySQL_, `SQLite 3`_, and Oracle_ are also supported. 305 305 306 306 .. _Python: http://www.python.org/ 307 307 .. _Apache 2: http://httpd.apache.org/ … … 310 310 .. _PostgreSQL: http://www.postgresql.org/ 311 311 .. _MySQL: http://www.mysql.com/ 312 312 .. _`SQLite 3`: http://www.sqlite.org/ 313 .. _Oracle: http://www.oracle.com/ 313 314 314 315 Do I lose anything by using Python 2.3 versus newer Python versions, such as Python 2.5? 315 316 ---------------------------------------------------------------------------------------- -
docs/install.txt
62 62 63 63 * If you're using SQLite, you'll need pysqlite_. Use version 2.0.3 or higher. 64 64 65 * If you're using Oracle, you'll need cx_Oracle_, version 4.3.1 or higher. 66 65 67 .. _PostgreSQL: http://www.postgresql.org/ 66 68 .. _MySQL: http://www.mysql.com/ 67 69 .. _Django's ticket system: http://code.djangoproject.com/report/1 … … 71 73 .. _SQLite: http://www.sqlite.org/ 72 74 .. _pysqlite: http://initd.org/tracker/pysqlite 73 75 .. _MySQL backend: ../databases/ 76 .. _cx_Oracle: http://www.python.net/crew/atuining/cx_Oracle/ 74 77 75 78 Remove any old versions of Django 76 79 ================================= -
tests/modeltests/datatypes/models.py
Property changes on: tests/modeltests/datatypes ___________________________________________________________________ Name: svn:ignore + *.pyc Property changes on: tests/modeltests/datatypes/__init__.py ___________________________________________________________________ Name: svn:eol-style + native
1 """ 2 1. Simple data types testing. 3 4 This is a basic model to test saving and loading boolean and date-related 5 types, which in the past were problematic for some database backends. 6 """ 7 8 from django.db import models 9 10 class Donut(models.Model): 11 name = models.CharField(maxlength=100) 12 is_frosted = models.BooleanField(default=False) 13 has_sprinkles = models.NullBooleanField() 14 baked_date = models.DateField(null=True) 15 baked_time = models.TimeField(null=True) 16 consumed_at = models.DateTimeField(null=True) 17 18 class Meta: 19 ordering = ('consumed_at',) 20 21 def __str__(self): 22 return self.name 23 24 __test__ = {'API_TESTS': """ 25 # No donuts are in the system yet. 26 >>> Donut.objects.all() 27 [] 28 29 >>> d = Donut(name='Apple Fritter') 30 31 # Ensure we're getting True and False, not 0 and 1 32 >>> d.is_frosted 33 False 34 >>> d.has_sprinkles 35 >>> d.has_sprinkles = True 36 >>> d.has_sprinkles 37 True 38 >>> d.save() 39 >>> d2 = Donut.objects.all()[0] 40 >>> d2 41 <Donut: Apple Fritter> 42 >>> d2.is_frosted 43 False 44 >>> d2.has_sprinkles 45 True 46 47 >>> import datetime 48 >>> d2.baked_date = datetime.date(year=1938, month=6, day=4) 49 >>> d2.baked_time = datetime.time(hour=5, minute=30) 50 >>> d2.consumed_at = datetime.datetime(year=2007, month=4, day=20, hour=16, minute=19, second=59) 51 >>> d2.save() 52 53 >>> d3 = Donut.objects.all()[0] 54 >>> d3.baked_date 55 datetime.date(1938, 6, 4) 56 >>> d3.baked_time 57 datetime.time(5, 30) 58 >>> d3.consumed_at 59 datetime.datetime(2007, 4, 20, 16, 19, 59) 60 """}