Ticket #1261: firebird-svn6652-full-updated.diff
File firebird-svn6652-full-updated.diff, 45.8 KB (added by , 17 years ago) |
---|
-
django/db/models/base.py
238 238 record_exists = False 239 239 if not pk_set or not record_exists: 240 240 field_names = [qn(f.column) for f in self._meta.fields if not isinstance(f, AutoField)] 241 #if connection.features.quote_autofields: 242 # field_names = [qn(f.column) for f in self._meta.fields] 241 243 db_values = [f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True)) for f in self._meta.fields if not isinstance(f, AutoField)] 242 244 # If the PK has been manually set, respect that. 243 245 if pk_set: 244 field_names += [f.column for f in self._meta.fields if isinstance(f, AutoField)] 246 if connection.features.quote_autofields: 247 field_names += [qn(f.column) for f in self._meta.fields if isinstance(f, AutoField)] 248 else: 249 field_names += [f.column for f in self._meta.fields if isinstance(f, AutoField)] 245 250 db_values += [f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True)) for f in self._meta.fields if isinstance(f, AutoField)] 246 251 placeholders = ['%s'] * len(field_names) 247 252 if self._meta.order_with_respect_to: -
django/db/models/fields/__init__.py
208 208 return value 209 209 210 210 def get_db_prep_lookup(self, lookup_type, value): 211 from django.db import connection 211 212 "Returns field's value prepared for database lookup." 212 213 if lookup_type in ('exact', 'regex', 'iregex', 'gt', 'gte', 'lt', 'lte', 'month', 'day', 'search'): 213 214 return [value] 214 215 elif lookup_type in ('range', 'in'): 215 216 return value 216 217 elif lookup_type in ('contains', 'icontains'): 218 if connection.features.uses_custom_icontains and lookup_type == 'icontains': 219 return [value] 217 220 return ["%%%s%%" % prep_for_like_query(value)] 218 221 elif lookup_type == 'iexact': 219 222 return [prep_for_like_query(value)] 220 223 elif lookup_type in ('startswith', 'istartswith'): 224 if connection.features.uses_custom_startswith: 225 return [value] 221 226 return ["%s%%" % prep_for_like_query(value)] 222 227 elif lookup_type in ('endswith', 'iendswith'): 223 228 return ["%%%s" % prep_for_like_query(value)] … … 480 485 defaults.update(kwargs) 481 486 return super(CharField, self).formfield(**defaults) 482 487 488 class ASCIICharField(CharField): 489 pass 490 483 491 # TODO: Maybe move this into contrib, because it's specialized. 484 492 class CommaSeparatedIntegerField(CharField): 485 493 def get_manipulator_field_objs(self): … … 589 597 # doesn't support microseconds. 590 598 if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'): 591 599 value = value.replace(microsecond=0) 592 value = smart_unicode(value) 600 #Firebird supports native datetime 601 if settings.DATABASE_ENGINE != 'firebird': 602 value = smart_unicode(value) 593 603 return Field.get_db_prep_save(self, value) 594 604 595 605 def get_db_prep_lookup(self, lookup_type, value): … … 997 1007 # doesn't support microseconds. 998 1008 if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'): 999 1009 value = value.replace(microsecond=0) 1000 if settings.DATABASE_ENGINE == 'oracle':1001 # cx_Oracle expectsa datetime.datetime to persist into TIMESTAMP field.1010 if settings.DATABASE_ENGINE in ('oracle', 'firebird'): 1011 # cx_Oracle and kinterbasdb expect a datetime.datetime to persist into TIMESTAMP field. 1002 1012 if isinstance(value, datetime.time): 1003 1013 value = datetime.datetime(1900, 1, 1, value.hour, value.minute, 1004 1014 value.second, value.microsecond) -
django/db/backends/__init__.py
45 45 autoindexes_primary_keys = True 46 46 inline_fk_references = True 47 47 needs_datetime_string_cast = True 48 needs_default_null = False 48 49 needs_upper_for_iops = False 49 50 supports_constraints = True 50 51 supports_tablespaces = False 52 quote_autofields = False 51 53 uses_case_insensitive_names = False 54 uses_custom_icontains = False 55 uses_custom_startswith = False 52 56 uses_custom_queryset = False 53 57 54 58 class BaseDatabaseOperations(object): … … 65 69 This SQL is executed when a table is created. 66 70 """ 67 71 return None 68 72 73 def cascade_delete_update_sql(self): 74 """ 75 Returns the SQL necessary to make a cascading deletes and updates 76 of foreign key references during a CREATE TABLE statement. 77 """ 78 return '' 79 69 80 def date_extract_sql(self, lookup_type, field_name): 70 81 """ 71 82 Given a lookup_type of 'year', 'month' or 'day', returns the SQL that -
django/db/backends/firebird/base.py
1 """ 2 Firebird database backend for Django. 3 4 Requires KInterbasDB 3.2: http://kinterbasdb.sourceforge.net/ 5 The egenix mx (mx.DateTime) is NOT required 6 7 Database charset should be UNICODE_FSS or UTF8 (FireBird 2.0+) 8 To use UTF8 encoding add FIREBIRD_CHARSET = 'UTF8' to your settings.py 9 UNICODE_FSS works with all versions and uses less memory 10 """ 11 12 from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, util 13 14 try: 15 import kinterbasdb as Database 16 except ImportError, e: 17 from django.core.exceptions import ImproperlyConfigured 18 raise ImproperlyConfigured, "Error loading KInterbasDB module: %s" % e 19 20 DatabaseError = Database.DatabaseError 21 IntegrityError = Database.IntegrityError 22 23 class DatabaseFeatures(BaseDatabaseFeatures): 24 needs_datetime_string_cast = False 25 needs_default_null = True 26 needs_upper_for_iops = True 27 quote_autofields = True 28 supports_constraints = False #some tests went strange without it 29 uses_custom_icontains = True #CONTAINING <value> op instead of LIKE %<value>% 30 uses_custom_startswith = True #STARTING WITH op. Faster than LIKE 31 uses_custom_queryset = True 32 33 class DatabaseOperations(BaseDatabaseOperations): 34 _max_name_length = 31 35 def __init__(self): 36 self._firebird_version = None 37 38 def get_generator_name(self, name): 39 return '%s_G' % util.truncate_name(name, self._max_name_length-2).upper() 40 41 def get_trigger_name(self, name): 42 return '%s_T' % util.truncate_name(name, self._max_name_length-2).upper() 43 44 def _get_firebird_version(self): 45 if self._firebird_version is None: 46 from django.db import connection 47 self._firebird_version = [int(val) for val in connection.server_version.split()[-1].split('.')] 48 return self._firebird_version 49 firebird_version = property(_get_firebird_version) 50 51 def _autoinc_sql_with_style(self, style, table_name, column_name): 52 """ 53 To simulate auto-incrementing primary keys in Firebird, we have to 54 create a generator and a trigger. 55 56 Create the generators and triggers names based only on table name 57 since django only support one auto field per model 58 """ 59 60 KWD = style.SQL_KEYWORD 61 TBL = style.SQL_TABLE 62 FLD = style.SQL_FIELD 63 64 generator_name = self.get_generator_name(table_name) 65 trigger_name = self.get_trigger_name(table_name) 66 column_name = self.quote_name(column_name) 67 table_name = self.quote_name(table_name) 68 69 generator_sql = "%s %s;" % ( KWD('CREATE GENERATOR'), 70 TBL(generator_name)) 71 trigger_sql = "\n".join([ 72 "%s %s %s %s" % ( \ 73 KWD('CREATE TRIGGER'), TBL(trigger_name), KWD('FOR'), 74 TBL(table_name)), 75 "%s 0 %s" % (KWD('ACTIVE BEFORE INSERT POSITION'), KWD('AS')), 76 KWD('BEGIN'), 77 " %s ((%s.%s %s) %s (%s.%s = 0)) %s" % ( \ 78 KWD('IF'), 79 KWD('NEW'), FLD(column_name), KWD('IS NULL'), 80 KWD('OR'), KWD('NEW'), FLD(column_name), 81 KWD('THEN') 82 ), 83 " %s" % KWD('BEGIN'), 84 " %s.%s = %s(%s, 1);" % ( \ 85 KWD('NEW'), FLD(column_name), 86 KWD('GEN_ID'), TBL(generator_name) 87 ), 88 " %s" % KWD('END'), 89 KWD('END') 90 ]) 91 return (generator_sql, trigger_sql) 92 93 def autoinc_sql(self, table_name, column_name): 94 # style argument disappeared, so we'll just import django's dummy 95 from django.core.management.color import no_style, color_style 96 return self._autoinc_sql_with_style(no_style(), table_name, column_name) 97 98 def max_name_length(self): 99 return self._max_name_length 100 101 def query_set_class(self, DefaultQuerySet): 102 from django.db import connection 103 from django.db.models.query import EmptyResultSet, GET_ITERATOR_CHUNK_SIZE, quote_only_if_word 104 105 class FirebirdQuerySet(DefaultQuerySet): 106 #TODO: Optimize for Firebird and take full advanatage of its power 107 # Now it's just a copy of django.db.models.query._QuerySet 108 # with LIMIT/OFFSET removed and FIRST/SKIP added 109 def _get_sql_clause(self): 110 from django.db.models.query import SortedDict, handle_legacy_orderlist, orderfield2column, fill_table_cache 111 qn = connection.ops.quote_name 112 opts = self.model._meta 113 114 # Construct the fundamental parts of the query: SELECT X FROM Y WHERE Z. 115 select = ["%s.%s" % (qn(opts.db_table), qn(f.column)) for f in opts.fields] 116 tables = [quote_only_if_word(t) for t in self._tables] 117 joins = SortedDict() 118 where = self._where[:] 119 params = self._params[:] 120 121 # Convert self._filters into SQL. 122 joins2, where2, params2 = self._filters.get_sql(opts) 123 joins.update(joins2) 124 where.extend(where2) 125 params.extend(params2) 126 127 # Add additional tables and WHERE clauses based on select_related. 128 if self._select_related: 129 fill_table_cache(opts, select, tables, where, 130 old_prefix=opts.db_table, 131 cache_tables_seen=[opts.db_table], 132 max_depth=self._max_related_depth) 133 134 # Add any additional SELECTs. 135 if self._select: 136 select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), qn(s[0])) for s in self._select.items()]) 137 138 # Start composing the body of the SQL statement. 139 sql = [" FROM", qn(opts.db_table)] 140 141 # Compose the join dictionary into SQL describing the joins. 142 if joins: 143 sql.append(" ".join(["%s %s AS %s ON %s" % (join_type, table, alias, condition) 144 for (alias, (table, join_type, condition)) in joins.items()])) 145 146 # Compose the tables clause into SQL. 147 if tables: 148 sql.append(", " + ", ".join(tables)) 149 150 # Compose the where clause into SQL. 151 if where: 152 sql.append(where and "WHERE " + " AND ".join(where)) 153 154 # ORDER BY clause 155 order_by = [] 156 if self._order_by is not None: 157 ordering_to_use = self._order_by 158 else: 159 ordering_to_use = opts.ordering 160 for f in handle_legacy_orderlist(ordering_to_use): 161 if f == '?': # Special case. 162 order_by.append(connection.ops.random_function_sql()) 163 else: 164 if f.startswith('-'): 165 col_name = f[1:] 166 order = "DESC" 167 else: 168 col_name = f 169 order = "ASC" 170 if "." in col_name: 171 table_prefix, col_name = col_name.split('.', 1) 172 table_prefix = qn(table_prefix) + '.' 173 else: 174 # Use the database table as a column prefix if it wasn't given, 175 # and if the requested column isn't a custom SELECT. 176 if "." not in col_name and col_name not in (self._select or ()): 177 table_prefix = qn(opts.db_table) + '.' 178 else: 179 table_prefix = '' 180 order_by.append('%s%s %s' % (table_prefix, qn(orderfield2column(col_name, opts)), order)) 181 if order_by: 182 sql.append("ORDER BY " + ", ".join(order_by)) 183 184 return select, " ".join(sql), params 185 186 def iterator(self): 187 "Performs the SELECT database lookup of this QuerySet." 188 from django.db.models.query import get_cached_row 189 190 try: 191 select, sql, params = self._get_sql_clause() 192 except EmptyResultSet: 193 raise StopIteration 194 195 # self._select is a dictionary, and dictionaries' key order is 196 # undefined, so we convert it to a list of tuples. 197 extra_select = self._select.items() 198 199 cursor = connection.cursor() 200 limit_offset_before = "" 201 if self._limit is not None: 202 limit_offset_before += "FIRST %s " % self._limit 203 if self._offset: 204 limit_offset_before += "SKIP %s " % self._offset 205 else: 206 assert self._offset is None, "'offset' is not allowed without 'limit'" 207 cursor.execute("SELECT " + limit_offset_before + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 208 fill_cache = self._select_related 209 fields = self.model._meta.fields 210 index_end = len(fields) 211 has_resolve_columns = hasattr(self, 'resolve_columns') 212 while 1: 213 rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE) 214 if not rows: 215 raise StopIteration 216 for row in rows: 217 if has_resolve_columns: 218 row = self.resolve_columns(row, fields) 219 if fill_cache: 220 obj, index_end = get_cached_row(klass=self.model, row=row, 221 index_start=0, max_depth=self._max_related_depth) 222 else: 223 obj = self.model(*row[:index_end]) 224 for i, k in enumerate(extra_select): 225 setattr(obj, k[0], row[index_end+i]) 226 yield obj 227 return FirebirdQuerySet 228 229 230 def quote_name(self, name): 231 # Trancate and quote once. No need for uppercase since 232 # we quote autofields too 233 if not name.startswith('"') and not name.endswith('"'): 234 name = '"%s"' % util.truncate_name(name, self._max_name_length) 235 return name #.upper() 236 237 def field_cast_sql(self, db_type): 238 return '%s' 239 240 def last_insert_id(self, cursor, table_name, pk_name): 241 stmt = 'SELECT GEN_ID(%s, 0) from RDB$DATABASE' 242 cursor.execute(stmt % self.get_generator_name(table_name)) 243 return cursor.fetchone()[0] 244 245 def date_extract_sql(self, lookup_type, column_name): 246 # lookup_type is 'year', 'month', 'day' 247 return "EXTRACT(%s FROM %s)" % (lookup_type, column_name) 248 249 def date_trunc_sql(self, lookup_type, column_name): 250 if lookup_type == 'year': 251 sql = "EXTRACT(year FROM %s)||'-01-01 00:00:00'" % column_name 252 elif lookup_type == 'month': 253 sql = "EXTRACT(year FROM %s)||'-'||EXTRACT(month FROM %s)||'-01 00:00:00'" % (column_name, column_name) 254 elif lookup_type == 'day': 255 sql = "EXTRACT(year FROM %s)||'-'||EXTRACT(month FROM %s)||'-'||EXTRACT(day FROM %s)||' 00:00:00'" % (column_name, column_name, column_name) 256 return "CAST(%s AS TIMESTAMP)" % sql 257 258 def cascade_delete_update_sql(self): 259 # Solves FK problems with sql_flush 260 return " ON DELETE CASCADE ON UPDATE CASCADE" 261 262 def datetime_cast_sql(self): 263 return None 264 265 def limit_offset_sql(self, limit, offset=None): 266 # limits are handled in custom FirebirdQuerySet 267 assert False, 'Limits are handled in a different way in Firebird' 268 return "" 269 270 def random_function_sql(self): 271 return "rand()" 272 273 def pk_default_value(self): 274 return "NULL" 275 276 def start_transaction_sql(self): 277 return "" 278 279 def sequence_reset_sql(self, style, model_list): 280 from django.db import models 281 output = [] 282 for model in model_list: 283 for f in model._meta.fields: 284 if isinstance(f, models.AutoField): 285 generator_name = self.get_generator_name(model._meta.db_table) 286 output.append("SET GENERATOR %s TO 0;" % generator_name) 287 break # Only one AutoField is allowed per model, so don't bother continuing. 288 for f in model._meta.many_to_many: 289 generator_name = self.get_generator_name(f.m2m_db_table()) 290 output.append("SET GENERATOR %s TO 0;" % generator_name) 291 return output 292 293 def sql_flush(self, style, tables, sequences): 294 if tables: 295 # FK constraints gave us a lot of trouble with default values 296 # that was a reason behind very ugly and dangerous code here 297 # Solved with "ON DELETE CASCADE" with all FK references 298 sql = ['%s %s %s;' % \ 299 (style.SQL_KEYWORD('DELETE'), 300 style.SQL_KEYWORD('FROM'), 301 style.SQL_FIELD(self.quote_name(table)) 302 ) for table in tables] 303 for generator_info in sequences: 304 table_name = generator_info['table'] 305 query = "SET GENERATOR %s TO 0;" % self.get_generator_name(table_name) 306 sql.append(query) 307 return sql 308 else: 309 return [] 310 311 # def fulltext_search_sql(self, field_name): 312 # return field_name + ' CONTAINING %s' 313 314 def drop_sequence_sql(self, table): 315 return "DROP GENERATOR %s;" % self.get_generator_name(table) 316 317 def last_executed_query(self, cursor, sql, params): 318 """ 319 Returns a string of the query last executed by the given cursor, with 320 placeholders replaced with actual values. 321 322 `sql` is the raw query containing placeholders, and `params` is the 323 sequence of parameters. These are used by default, but this method 324 exists for database backends to provide a better implementation 325 according to their own quoting schemes. 326 """ 327 from django.utils.encoding import smart_unicode, force_unicode 328 329 # Convert params to contain Unicode values. 330 to_unicode = lambda s: force_unicode(s, strings_only=True) 331 if isinstance(params, (list, tuple)): 332 u_params = tuple([to_unicode(val) for val in params]) 333 else: 334 u_params = dict([(to_unicode(k), to_unicode(v)) for k, v in params.items()]) 335 try: 336 #Extracts sql right from KInterbasDB's prepared statement 337 return smart_unicode(cursor.query) % u_params 338 except TypeError: 339 return smart_unicode(sql) % u_params 340 341 class FirebirdCursorWrapper(object): 342 """ 343 Django uses "format" ('%s') style placeholders, but firebird uses "qmark" ('?') style. 344 This fixes it -- but note that if you want to use a literal "%s" in a query, 345 you'll need to use "%%s". 346 347 We also do all automatic type conversions here. 348 """ 349 import kinterbasdb.typeconv_datetime_stdlib as tc_dt 350 import kinterbasdb.typeconv_fixed_decimal as tc_fd 351 import kinterbasdb.typeconv_text_unicode as tc_tu 352 import django.utils.encoding as dj_ue 353 354 def timestamp_conv_in(self, timestamp): 355 if isinstance(timestamp, basestring): 356 #Replaces 6 digits microseconds to 4 digits allowed in Firebird 357 timestamp = timestamp[:24] 358 return self.tc_dt.timestamp_conv_in(timestamp) 359 360 def time_conv_in(self, value): 361 import datetime 362 if isinstance(value, datetime.datetime): 363 value = datetime.time(value.hour, value.minute, value.second, value.micosecond) 364 return self.tc_dt.time_conv_in(value) 365 366 def ascii_conv_in(self, text): 367 return self.dj_eu.smart_str(text, 'ascii') 368 369 def unicode_conv_in(self, text): 370 return self.tc_tu.unicode_conv_in((self.dj_ue.force_unicode(text[0]), self.FB_CHARSET_CODE)) 371 372 def blob_conv_in(self, text): 373 return self.tc_tu.unicode_conv_in((self.dj_ue.force_unicode(text), self.FB_CHARSET_CODE)) 374 375 def blob_conv_out(self, text): 376 return self.tc_tu.unicode_conv_out((text, self.FB_CHARSET_CODE)) 377 378 def __init__(self, cursor): 379 from django.conf import settings 380 self.FB_CHARSET_CODE = 3 #UNICODE_FSS 381 if hasattr(settings, 'FIREBIRD_CHARSET'): 382 if settings.FIREBIRD_CHARSET == 'UTF8': 383 self.FB_CHARSET_CODE = 4 # UTF-8 with Firebird 2.0+ 384 self.cursor = cursor 385 386 # Prepared Statement 387 # http://kinterbasdb.sourceforge.net/dist_docs/usage.html#adv_prepared_statements 388 # Need to decide wether they are useful or not 389 # Maybe add prepare, execute_prep and executemany_pep methods here 390 # and rewrite QuerySet to take advantage of them? 391 # Could speed the things up 392 self._statement = None 393 self.cursor.set_type_trans_in({ 394 'DATE': self.tc_dt.date_conv_in, 395 'TIME': self.time_conv_in, 396 'TIMESTAMP': self.timestamp_conv_in, 397 'FIXED': self.tc_fd.fixed_conv_in_imprecise, 398 'TEXT': self.ascii_conv_in, 399 'TEXT_UNICODE': self.unicode_conv_in, 400 'BLOB': self.blob_conv_in 401 }) 402 self.cursor.set_type_trans_out({ 403 'DATE': self.tc_dt.date_conv_out, 404 'TIME': self.tc_dt.time_conv_out, 405 'TIMESTAMP': self.tc_dt.timestamp_conv_out, 406 'FIXED': self.tc_fd.fixed_conv_out_imprecise, 407 'TEXT': self.dj_ue.force_unicode, 408 'TEXT_UNICODE': self.tc_tu.unicode_conv_out, 409 'BLOB': self.blob_conv_out 410 }) 411 412 def _get_query(self): 413 if self._statement: 414 return self._statement.sql 415 def _get_statement(self): 416 if self._statement: 417 return self._statement 418 query = property(_get_query) 419 statement = property(_get_statement) 420 421 def execute(self, query, params=()): 422 query = self.convert_query(query, len(params)) 423 if self._get_query() != query: 424 try: 425 self._statement = self.cursor.prep(query) 426 except Database.ProgrammingError, e: 427 print query % params 428 raise DatabaseError, e 429 return self.cursor.execute(self._statement, params) 430 431 def executemany(self, query, param_list): 432 try: 433 query = self.convert_query(query, len(param_list[0])) 434 except IndexError: 435 return None 436 if self._get_query() != query: 437 self._statement = self.cursor.prep(query) 438 return self.cursor.executemany(self._statement, param_list) 439 440 def convert_query(self, query, num_params): 441 try: 442 return query % tuple("?" * num_params) 443 except TypeError, e: 444 print query, num_params 445 raise TypeError, e 446 447 def __getattr__(self, attr): 448 if attr in self.__dict__: 449 return self.__dict__[attr] 450 else: 451 return getattr(self.cursor, attr) 452 453 class DatabaseWrapper(BaseDatabaseWrapper): 454 features = DatabaseFeatures() 455 ops = DatabaseOperations() 456 operators = { 457 'exact': '= %s', 458 'iexact': '= UPPER(%s)', 459 'contains': "LIKE %s ESCAPE'\\'", 460 'icontains': 'CONTAINING %s', #case is ignored 461 'gt': '> %s', 462 'gte': '>= %s', 463 'lt': '< %s', 464 'lte': '<= %s', 465 'startswith': 'STARTING WITH %s', #looks to be faster then LIKE 466 'endswith': "LIKE %s ESCAPE'\\'", 467 'istartswith': 'STARTING WITH UPPER(%s)', 468 'iendswith': "LIKE UPPER(%s) ESCAPE'\\'", 469 } 470 _current_cursor = None 471 def _connect(self, settings): 472 if settings.DATABASE_NAME == '': 473 from django.core.exceptions import ImproperlyConfigured 474 raise ImproperlyConfigured, "You need to specify DATABASE_NAME in your Django settings file." 475 charset = 'UNICODE_FSS' 476 if hasattr(settings, 'FIREBIRD_CHARSET'): 477 if settings.FIREBIRD_CHARSET == 'UTF8': 478 charset = 'UTF8' 479 kwargs = {'charset' : charset } 480 if settings.DATABASE_HOST: 481 kwargs['dsn'] = "%s:%s" % (settings.DATABASE_HOST, settings.DATABASE_NAME) 482 else: 483 kwargs['dsn'] = "localhost:%s" % settings.DATABASE_NAME 484 if settings.DATABASE_USER: 485 kwargs['user'] = settings.DATABASE_USER 486 if settings.DATABASE_PASSWORD: 487 kwargs['password'] = settings.DATABASE_PASSWORD 488 self.connection = Database.connect(**kwargs) 489 assert self.charset == charset 490 try: 491 self.connection.execute_immediate(""" 492 DECLARE EXTERNAL FUNCTION rand 493 RETURNS DOUBLE PRECISION 494 BY VALUE ENTRY_POINT 'IB_UDF_rand' MODULE_NAME 'ib_udf'; 495 """) 496 except Database.ProgrammingError: 497 pass #Already defined 498 499 def cursor(self, name=None): 500 #Cursors can be named 501 #http://kinterbasdb.sourceforge.net/dist_docs/usage.html#adv_named_cursors 502 #and maybe useful for scrolling updates and deletes 503 from django.conf import settings 504 cursor = self._cursor(settings, name) 505 if settings.DEBUG: 506 return self.make_debug_cursor(cursor) 507 return cursor 508 509 def _cursor(self, settings, name): 510 if self.connection is None: 511 self._connect(settings) 512 cursor = self.connection.cursor() 513 if name: 514 cursor.name = name 515 cursor = FirebirdCursorWrapper(cursor) 516 self._current_cursor = cursor 517 return cursor 518 519 #Returns query from prepared statement 520 def _get_query(self): 521 if self._current_cursor: 522 return self._current_cursor.query 523 query = property(_get_query) 524 #Returns prepared statement itself 525 def _get_statement(self): 526 if self._current_cursor: 527 return self._current_cursor.statement 528 statement = property(_get_statement) 529 530 531 def __getattr__(self, attr): 532 if attr in self.__dict__: 533 return self.__dict__[attr] 534 else: 535 return getattr(self.connection, attr) 536 537 -
django/db/backends/firebird/client.py
1 from django.conf import settings 2 import os 3 4 def runshell(): 5 args = [settings.DATABASE_NAME] 6 args += ["-u %s" % settings.DATABASE_USER] 7 if settings.DATABASE_PASSWORD: 8 args += ["-p %s" % settings.DATABASE_PASSWORD] 9 if 'FIREBIRD' not in os.environ: 10 path = '/opt/firebird/bin/' 11 os.system(path + 'isql ' + ' '.join(args)) -
django/db/backends/firebird/introspection.py
1 from django.db import transaction 2 from django.db.backends.firebird.base import DatabaseOperations 3 4 quote_name = DatabaseOperations().quote_name 5 6 def get_table_list(cursor): 7 "Returns a list of table names in the current database." 8 cursor.execute(""" 9 SELECT rdb$relation_name FROM rdb$relations 10 WHERE rdb$system_flag = 0 AND rdb$view_blr IS NULL ORDER BY rdb$relation_name""") 11 return [str(row[0].strip().lower()) for row in cursor.fetchall()] 12 13 def get_table_description(cursor, table_name): 14 "Returns a description of the table, with the DB-API cursor.description interface." 15 #cursor.execute("SELECT FIRST 1 * FROM %s" % quote_name(table_name)) 16 #return cursor.description 17 # (name, type_code, display_size, internal_size, precision, scale, null_ok) 18 cursor.execute(""" 19 SELECT DISTINCT R.RDB$FIELD_NAME AS FNAME, 20 F.RDB$FIELD_TYPE AS FTYPE, 21 F.RDB$FIELD_LENGTH AS FLENGTH, 22 F.RDB$FIELD_PRECISION AS FPRECISION, 23 F.RDB$FIELD_SCALE AS FSCALE, 24 R.RDB$NULL_FLAG AS NULL_FLAG, 25 R.RDB$FIELD_POSITION 26 FROM RDB$RELATION_FIELDS R 27 JOIN RDB$FIELDS F ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME 28 WHERE F.RDB$SYSTEM_FLAG=0 and R.RDB$RELATION_NAME= %s 29 ORDER BY R.RDB$FIELD_POSITION 30 """, (table_name,)) 31 return [(row[0].lower().rstrip(), row[1], row[2], row[2] or 0, row[3], row[4], row[5] and True or False) for row in cursor.fetchall()] 32 33 34 def get_relations(cursor, table_name): 35 """ 36 Returns a dictionary of {field_index: (field_index_other_table, other_table)} 37 representing all relationships to the given table. Indexes are 0-based. 38 """ 39 cursor.execute(""" 40 SELECT seg.rdb$field_name, seg_ref.rdb$field_name, idx_ref.rdb$relation_name 41 FROM rdb$indices idx 42 INNER JOIN rdb$index_segments seg 43 ON seg.rdb$index_name = idx.rdb$index_name 44 INNER JOIN rdb$indices idx_ref 45 ON idx_ref.rdb$index_name = idx.rdb$foreign_key 46 INNER JOIN rdb$index_segments seg_ref 47 ON seg_ref.rdb$index_name = idx_ref.rdb$index_name 48 WHERE idx.rdb$relation_name = %s 49 AND idx.rdb$foreign_key IS NOT NULL""", [table_name]) 50 51 relations = {} 52 for row in cursor.fetchall(): 53 relations[row[0].rstrip()] = (row[1].strip(), row[2].strip()) 54 return relations 55 56 def get_indexes(cursor, table_name): 57 """ 58 Returns a dictionary of fieldname -> infodict for the given table, 59 where each infodict is in the format: 60 {'primary_key': boolean representing whether it's the primary key, 61 'unique': boolean representing whether it's a unique index} 62 """ 63 64 # This query retrieves each field name and index type on the given table. 65 cursor.execute(""" 66 SELECT seg.rdb$field_name, const.rdb$constraint_type 67 FROM rdb$relation_constraints const 68 LEFT JOIN rdb$index_segments seg 69 ON seg.rdb$index_name = const.rdb$index_name 70 WHERE const.rdb$relation_name = %s 71 AND (const.rdb$constraint_type = 'PRIMARY KEY' 72 OR const.rdb$constraint_type = 'UNIQUE')""", [table_name]) 73 indexes = {} 74 for row in cursor.fetchall(): 75 indexes[row[0].strip()] = { 76 'primary_key': ('PRIMARY KEY' == row[1].strip()), 77 'unique': ('UNIQUE' == row[1].strip())} 78 return indexes 79 80 # Maps type codes to Django Field types. 81 # !todo 82 DATA_TYPES_REVERSE = { 83 7: 'BooleanField', 84 7: 'SmallIntegerField', 85 8: 'IntegerField', 86 261: 'TextField', 87 37: 'IPAddressField', 88 37: 'CharField', 89 12: 'DateField', 90 13: 'TimeField', 91 35: 'DateTimeField', 92 10: 'FloatField', 93 } -
django/db/backends/firebird/creation.py
1 # This dictionary maps Field objects to their associated Firebird column 2 # types, as strings. Column-type strings can contain format strings; they'll 3 # be interpolated against the values of Field.__dict__ before being output. 4 # If a column type is set to None, it won't be included in the output. 5 6 import sys, os.path 7 from kinterbasdb import connect, create_database 8 from django.core.management import call_command 9 10 #TODO: Implement CHECKs 11 DATA_TYPES = { 12 'ASCIICharField': 'varchar(%(max_length)s) CHARACTER SET ASCII', 13 'AutoField': 'integer', 14 'BooleanField': 'smallint', # CHECK ("%(column)s" IN (0,1))', 15 'CharField': 'varchar(%(max_length)s)', 16 'CommaSeparatedIntegerField': 'varchar(%(max_length)s) CHARACTER SET ASCII', 17 'DateField': 'date', 18 'DateTimeField': 'timestamp', 19 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 20 'FileField': 'varchar(%(max_length)s)', 21 'FilePathField': 'varchar(%(max_length)s)', 22 'FloatField': 'double precision', 23 'ImageField': 'varchar(%(max_length)s) CHARACTER SET ASCII', 24 'IntegerField': 'integer', 25 'IPAddressField': 'varchar(15) CHARACTER SET ASCII', 26 'NullBooleanField': 'smallint', #CHECK (("%(column)"s IN (0,1)) OR ("%(column)s" IS NULL))', 27 'OneToOneField': 'integer', 28 'PhoneNumberField': 'varchar(20)', # CHARACTER SET ASCII', 29 'PositiveIntegerField': 'integer', # CHECK ("%(column)s" >= 0)', 30 'PositiveSmallIntegerField': 'smallint', 31 'SlugField': 'varchar(%(max_length)s)', 32 'SmallIntegerField': 'smallint', 33 'TextField': 'blob sub_type text', 34 'TimeField': 'time', 35 'URLField': 'varchar(%(max_length)s) CHARACTER SET ASCII', 36 'USStateField': 'varchar(2) CHARACTER SET ASCII', 37 } 38 39 TEST_DATABASE_PREFIX = 'test_' 40 41 def create_test_db(settings, connection, verbosity, autoclobber): 42 # KInterbasDB supports dynamic database creation and deletion 43 # via the module-level function create_database and the method Connection.drop_database. 44 45 if settings.TEST_DATABASE_NAME: 46 TEST_DATABASE_NAME = settings.TEST_DATABASE_NAME 47 else: 48 dbnametuple = os.path.split(settings.DATABASE_NAME) 49 TEST_DATABASE_NAME = os.path.join(dbnametuple[0], TEST_DATABASE_PREFIX + dbnametuple[1]) 50 51 dsn = "localhost:%s" % TEST_DATABASE_NAME 52 if settings.DATABASE_HOST: 53 dsn = "%s:%s" % (settings.DATABASE_HOST, TEST_DATABASE_NAME) 54 55 if os.path.isfile(TEST_DATABASE_NAME): 56 sys.stderr.write("Database %s already exists\n" % TEST_DATABASE_NAME) 57 if not autoclobber: 58 confirm = raw_input("Type 'yes' if you would like to try deleting the test database '%s', or 'no' to cancel: " % TEST_DATABASE_NAME) 59 if autoclobber or confirm == 'yes': 60 if verbosity >= 1: 61 print "Destroying old test database..." 62 old_connection = connect(dsn=dsn, user=settings.DATABASE_USER, password=settings.DATABASE_PASSWORD) 63 old_connection.drop_database() 64 else: 65 print "Tests cancelled." 66 sys.exit(1) 67 68 if verbosity >= 1: 69 print "Creating test database..." 70 try: 71 charset = 'UNICODE_FSS' 72 if hasattr(settings, 'FIREBIRD_CHARSET'): 73 if settings.FIREBIRD_CHARSET == 'UTF8': 74 charset='UTF8' 75 create_database("create database '%s' user '%s' password '%s' default character set %s" % \ 76 (dsn, settings.DATABASE_USER, settings.DATABASE_PASSWORD, charset)) 77 except Exception, e: 78 sys.stderr.write("Got an error creating the test database: %s\n" % e) 79 sys.exit(2) 80 81 82 connection.close() 83 settings.DATABASE_NAME = TEST_DATABASE_NAME 84 85 call_command('syncdb', verbosity=verbosity, interactive=False) 86 87 if settings.CACHE_BACKEND.startswith('db://'): 88 cache_name = settings.CACHE_BACKEND[len('db://'):] 89 call_command('createcachetable', cache_name) 90 91 # Get a cursor (even though we don't need one yet). This has 92 # the side effect of initializing the test database. 93 cursor = connection.cursor() 94 95 return TEST_DATABASE_NAME 96 97 def destroy_test_db(settings, connection, old_database_name, verbosity): 98 # KInterbasDB supports dynamic database deletion via the method Connection.drop_database. 99 if verbosity >= 1: 100 print "Destroying test database..." 101 connection.drop_database() 102 103 -
django/core/management/sql.py
263 263 # Make the definition (e.g. 'foo VARCHAR(30)') for this field. 264 264 field_output = [style.SQL_FIELD(qn(f.column)), 265 265 style.SQL_COLTYPE(col_type)] 266 field_output.append(style.SQL_KEYWORD('%sNULL' % (not f.null and 'NOT ' or ''))) 266 nullstring = "" 267 if connection.features.needs_default_null: 268 nullstring = "DEFAULT " 269 field_output.append(style.SQL_KEYWORD('%sNULL' % (not f.null and 'NOT ' or nullstring))) 267 270 if f.unique and (not f.primary_key or connection.features.allows_unique_and_pk): 268 271 field_output.append(style.SQL_KEYWORD('UNIQUE')) 269 272 if f.primary_key: … … 276 279 if inline_references and f.rel.to in known_models: 277 280 field_output.append(style.SQL_KEYWORD('REFERENCES') + ' ' + \ 278 281 style.SQL_TABLE(qn(f.rel.to._meta.db_table)) + ' (' + \ 279 style.SQL_FIELD(qn(f.rel.to._meta.get_field(f.rel.field_name).column)) + ')' + 280 connection.ops. deferrable_sql()282 style.SQL_FIELD(qn(f.rel.to._meta.get_field(f.rel.field_name).column)) + ')' + \ 283 connection.ops.cascade_delete_update_sql() + connection.ops.deferrable_sql() 281 284 ) 282 285 else: 283 286 # We haven't yet created the table to which this field … … 335 338 final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % \ 336 339 (qn(r_table), truncate_name(r_name, connection.ops.max_name_length()), 337 340 qn(r_col), qn(table), qn(col), 341 connection.ops.cascade_delete_update_sql(), 338 342 connection.ops.deferrable_sql())) 339 343 del pending_references[model] 340 344 return final_output … … 364 368 tablespace_sql)) 365 369 if inline_references: 366 370 deferred = [] 367 table_output.append(' %s %s %s %s (%s)%s ,' %371 table_output.append(' %s %s %s %s (%s)%s%s,' % 368 372 (style.SQL_FIELD(qn(f.m2m_column_name())), 369 373 style.SQL_COLTYPE(models.ForeignKey(model).db_type()), 370 374 style.SQL_KEYWORD('NOT NULL REFERENCES'), 371 375 style.SQL_TABLE(qn(opts.db_table)), 372 376 style.SQL_FIELD(qn(opts.pk.column)), 377 connection.ops.cascade_delete_update_sql(), 373 378 connection.ops.deferrable_sql())) 374 table_output.append(' %s %s %s %s (%s)%s ,' %379 table_output.append(' %s %s %s %s (%s)%s%s,' % 375 380 (style.SQL_FIELD(qn(f.m2m_reverse_name())), 376 381 style.SQL_COLTYPE(models.ForeignKey(f.rel.to).db_type()), 377 382 style.SQL_KEYWORD('NOT NULL REFERENCES'), 378 383 style.SQL_TABLE(qn(f.rel.to._meta.db_table)), 379 384 style.SQL_FIELD(qn(f.rel.to._meta.pk.column)), 385 connection.ops.cascade_delete_update_sql(), 380 386 connection.ops.deferrable_sql())) 381 387 else: 382 388 table_output.append(' %s %s %s,' % … … 412 418 (qn(r_table), 413 419 truncate_name(r_name, connection.ops.max_name_length()), 414 420 qn(r_col), qn(table), qn(col), 421 connection.ops.cascade_delete_update_sql(), 415 422 connection.ops.deferrable_sql())) 416 423 417 424 # Add any extra SQL needed to support auto-incrementing PKs -
django/contrib/contenttypes/models.py
1 1 from django.db import models 2 2 from django.utils.translation import ugettext_lazy as _ 3 3 from django.utils.encoding import smart_unicode 4 from django.conf import settings 4 5 5 6 CONTENT_TYPE_CACHE = {} 6 7 class ContentTypeManager(models.Manager): … … 31 32 global CONTENT_TYPE_CACHE 32 33 CONTENT_TYPE_CACHE = {} 33 34 34 class ContentType(models.Model): 35 class ContentType(models.Model): 35 36 name = models.CharField(max_length=100) 36 app_label = models.CharField(max_length=100) 37 model = models.CharField(_('python model class name'), max_length=100) 37 # Need this because of Firebird restrictions on index key size < 252 bytes 38 if settings.DATABASE_ENGINE == 'firebird': 39 app_label = models.ASCIICharField(max_length=96) 40 model = models.ASCIICharField(_('python model class name'), max_length=96) 41 else: 42 app_label = models.CharField(max_length=100) 43 model = models.CharField(_('python model class name'), max_length=100) 38 44 objects = ContentTypeManager() 39 45 class Meta: 40 46 verbose_name = _('content type') -
django/contrib/auth/models.py
6 6 from django.contrib.contenttypes.models import ContentType 7 7 from django.utils.encoding import smart_str 8 8 from django.utils.translation import ugettext_lazy as _ 9 from django.conf import settings 9 10 import datetime 10 11 import urllib 11 12 … … 72 73 """ 73 74 name = models.CharField(_('name'), max_length=50) 74 75 content_type = models.ForeignKey(ContentType) 75 codename = models.CharField(_('codename'), max_length=100) 76 # Need this because of Firebird restrictions on index key size < 252 bytes 77 if settings.DATABASE_ENGINE == 'firebird': 78 codename = models.ASCIICharField(_('codename'), max_length=100) 79 else: 80 codename = models.CharField(_('codename'), max_length=100) 76 81 77 82 class Meta: 78 83 verbose_name = _('permission') -
tests/regressiontests/serializers_regress/tests.py
266 266 data[2]._meta.get_field('data').empty_strings_allowed and 267 267 data[3] is None)] 268 268 269 #JUST SKIP some for now.... 270 if settings.DATABASE_ENGINE == 'firebird': 271 test_data = test_data[:5] 272 269 273 # Dynamically create serializer tests to ensure that all 270 274 # registered serializers are automatically tested. 271 275 class SerializerTests(unittest.TestCase): -
tests/regressiontests/serializers_regress/models.py
102 102 """This is a model that can be used as 103 103 something for other models to point at""" 104 104 105 data = models. CharField(max_length=30)105 data = models.ASCIICharField(max_length=30) 106 106 107 107 class UniqueAnchor(models.Model): 108 108 """This is a model that can be used as 109 109 something for other models to point at""" 110 110 111 data = models. CharField(unique=True, max_length=30)111 data = models.ASCIICharField(unique=True, max_length=30) 112 112 113 113 class FKData(models.Model): 114 114 data = models.ForeignKey(Anchor, null=True) … … 144 144 data = models.BooleanField(primary_key=True) 145 145 146 146 class CharPKData(models.Model): 147 data = models. CharField(max_length=30, primary_key=True)147 data = models.ASCIICharField(max_length=30, primary_key=True) 148 148 149 149 # class DatePKData(models.Model): 150 150 # data = models.DateField(primary_key=True)