Django

Code

Ticket #1261: release-0.96-firebird.diff

File release-0.96-firebird.diff, 31.8 kB (added by david@david-elias.net, 1 year ago)

Patch against 0.96 with backend included

  • django/test/utils.py

    old new  
    11import sys, time 
    22from django.conf import settings 
    3 from django.db import connection, transaction, backend 
     3from django.db import connection, transaction, backend, get_creation_module 
    44from django.core import management 
    55from django.dispatch import dispatcher 
    66from django.test import signals 
     
    4444        connection.connection.set_isolation_level(0) 
    4545 
    4646def 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     
    4753    if verbosity >= 1: 
    4854        print "Creating test database..." 
    4955    # If we're using SQLite, it's more convenient to test against an 
     
    9298    cursor = connection.cursor() 
    9399 
    94100def 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     
    95107    # Unless we're using SQLite, remove the test database to clean up after 
    96108    # ourselves. Connect to the previous database (not the test database) 
    97109    # to do so, because it's not allowed to delete a database while being 
  • django/db/models/base.py

    old new  
    205205        record_exists = True 
    206206        if pk_set: 
    207207            # Determine whether a record with the primary key already exists. 
    208             cursor.execute("SELECT 1 FROM %s WHERE %s=%%s LIMIT 1" % \ 
     208            check_sql = 'SELECT 1 FROM %s WHERE %s=%%s LIMIT 1' 
     209            if settings.DATABASE_ENGINE == 'firebird': 
     210                check_sql = 'SELECT FIRST 1 1 FROM %s WHERE %s=%%s' 
     211            cursor.execute(check_sql % \ 
    209212                (backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column)), [pk_val]) 
    210213            # If it does already exist, do an UPDATE. 
    211214            if cursor.fetchone(): 
  • django/db/models/fields/related.py

    old new  
    335335                    (target_col_name, self.join_table, source_col_name, 
    336336                    target_col_name, ",".join(['%s'] * len(new_ids))), 
    337337                    [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)]) 
     338                rows = cursor.fetchall() 
     339                if rows: 
     340                    existing_ids = set([row[0] for row in rows]) 
    340341                else: 
    341342                    existing_ids = set() 
    342343 
  • django/db/models/query.py

    old new  
    22from django.db.models.fields import DateField, FieldDoesNotExist 
    33from django.db.models.fields.generic import GenericRelation 
    44from django.db.models import signals 
     5from django.conf import settings 
    56from django.dispatch import dispatcher 
    67from django.utils.datastructures import SortedDict 
    78import operator 
     
    179180        # undefined, so we convert it to a list of tuples. 
    180181        extra_select = self._select.items() 
    181182 
     183        pre_columns = "" 
     184        if settings.DATABASE_ENGINE == 'firebird' and self._limit is not None: 
     185            pre_columns += "FIRST %s " % self._limit 
     186            if self._offset: 
     187                pre_columns += "SKIP %s " % self._offset 
     188        if self._distinct: 
     189            pre_columns += "DISTINCT " 
    182190        cursor = connection.cursor() 
    183         cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 
     191        cursor.execute("SELECT " + pre_columns + ",".join(select) + sql, params) 
    184192        fill_cache = self._select_related 
    185193        index_end = len(self.model._meta.fields) 
    186194        while 1: 
     
    502510 
    503511        # Compose the join dictionary into SQL describing the joins. 
    504512        if joins: 
    505             sql.append(" ".join(["%s %s AS %s ON %s" % (join_type, table, alias, condition) 
     513            sql.append(" ".join(["%s %s %s ON %s" % (join_type, table, alias, condition) 
    506514                            for (alias, (table, join_type, condition)) in joins.items()])) 
    507515 
    508516        # Compose the tables clause into SQL. 
     
    717725        table_prefix = backend.quote_name(table_prefix[:-1])+'.' 
    718726    field_name = backend.quote_name(field_name) 
    719727    try: 
    720         return '%s%s %s' % (table_prefix, field_name, (backend.OPERATOR_MAPPING[lookup_type] % '%s')) 
     728        lookup_sql = '%s%s %s' 
     729        if settings.DATABASE_ENGINE == 'firebird' and lookup_type in ('iexact', 'icontains', 'istartswith', 'iendswith'): 
     730            lookup_sql = 'UPPER(%s%s) %s' 
     731        return lookup_sql % (table_prefix, field_name, (backend.OPERATOR_MAPPING[lookup_type] % '%s')) 
    721732    except KeyError: 
    722733        pass 
    723734    if lookup_type == 'in': 
  • django/db/backends/util.py

    old new  
    1 import datetime 
     1import datetime, md5 
    22from time import time 
    33 
    44class CursorDebugWrapper(object): 
     
    3838        else: 
    3939            return getattr(self.cursor, attr) 
    4040 
     41def truncate_name(name, length=None): 
     42    """Shortens a string to a repeatable mangled version with the given length. 
     43    """ 
     44    if length is None or len(name) <= length: 
     45        return name 
     46    hash = md5.md5(name).hexdigest()[:4] 
     47    return '%s%s' % (name[:length-4], hash) 
     48 
    4149############################################### 
    4250# Converters from database (string) to Python # 
    4351############################################### 
  • django/db/backends/firebird/base.py

    old new  
     1""" 
     2Firebird database backend for Django. 
     3 
     4Requires kinterbasdb: http://kinterbasdb.sourceforge.net/ 
     5""" 
     6 
     7from django.conf import settings 
     8from django.db.backends import util 
     9import re 
     10try: 
     11    import kinterbasdb as Database 
     12    import kinterbasdb.typeconv_datetime_stdlib as typeconv_datetime 
     13except ImportError, e: 
     14    from django.core.exceptions import ImproperlyConfigured 
     15    raise ImproperlyConfigured, "Error loading kinterbasdb module: %s" % e 
     16 
     17DatabaseError = Database.DatabaseError 
     18Database.init(type_conv=199) 
     19 
     20try: 
     21    # Only exists in Python 2.4+ 
     22    from threading import local 
     23except ImportError: 
     24    # Import copy of _thread_local.py from Python 2.4 
     25    from django.utils._threading_local import local 
     26 
     27server_version = None 
     28 
     29def unicode_conv_in(text): 
     30    #Type converter for columns with charsets NONE, OCTETS, or ASCII 
     31    if isinstance(text, unicode): 
     32        return text.encode(settings.DEFAULT_CHARSET) 
     33    return text 
     34 
     35def timestamp_conv_in(datetime): 
     36    #Type converter for datetime casted strings. 
     37    #Replaces 6 digits microseconds to 4 digits allowed in Firebird 
     38    if isinstance(datetime, basestring) and datetime.find('.') > 0 and len(datetime) == 26: 
     39        datetime = datetime[0:-2] 
     40    return typeconv_datetime.timestamp_conv_in(datetime) 
     41 
     42class DatabaseWrapper(local): 
     43    def __init__(self, **kwargs): 
     44        self.connection = None 
     45        self.queries = [] 
     46        self.options = kwargs 
     47 
     48    def cursor(self): 
     49        if self.connection is None: 
     50            if settings.DATABASE_NAME == '': 
     51                from django.core.exceptions import ImproperlyConfigured 
     52                raise ImproperlyConfigured, "You need to specify DATABASE_NAME in your Django settings file." 
     53            kwargs = {'database': settings.DATABASE_NAME} 
     54            if settings.DATABASE_HOST: 
     55                kwargs['host'] = settings.DATABASE_HOST 
     56            if settings.DATABASE_USER: 
     57                kwargs['user'] = settings.DATABASE_USER 
     58            if settings.DATABASE_PASSWORD: 
     59                kwargs['password'] = settings.DATABASE_PASSWORD 
     60            self.connection = Database.connect(**kwargs) 
     61            self.connection.set_type_trans_in({ 
     62                'TEXT': unicode_conv_in, 
     63                'BLOB': unicode_conv_in, 
     64                'TIMESTAMP': timestamp_conv_in 
     65            }) 
     66            global server_version 
     67            if not server_version: 
     68                import re 
     69                version_re = re.compile('.*Firebird\s([\d\.]+)') 
     70                m = version_re.match(self.connection.server_version) 
     71                if not m: 
     72                    raise Exception('Unable to determine Firebird version from version string %r' % self.connection.server_version) 
     73                server_version = m.groups()[0] 
     74        cursor = FirebirdCursorWrapper(self.connection) 
     75        if settings.DEBUG: 
     76            return util.CursorDebugWrapper(cursor, self) 
     77        return cursor 
     78 
     79    def _commit(self): 
     80        if self.connection is not None: 
     81            return self.connection.commit() 
     82 
     83    def _rollback(self): 
     84        if self.connection is not None: 
     85            return self.connection.rollback() 
     86 
     87    def close(self): 
     88        if self.connection is not None: 
     89            self.connection.close() 
     90            self.connection = None 
     91 
     92class FirebirdCursorWrapper(Database.Cursor): 
     93    """ 
     94    Django uses "format" ('%s') style placeholders, but firebird uses "qmark" ('?') style. 
     95    This fixes it -- but note that if you want to use a literal "%s" in a query, 
     96    you'll need to use "%%s". 
     97    """ 
     98    def execute(self, query, params=()): 
     99        query = self._convert_query(query, len(params)) 
     100        #print "%s %s" % (query, params) 
     101        return Database.Cursor.execute(self, query, params) 
     102 
     103    def executemany(self, query, params): 
     104        query = self._convert_query(query, len(params[0])) 
     105        return Database.Cursor.executemany(self, query, params) 
     106 
     107    def _convert_query(self, query, num_params): 
     108        return query % tuple("?" * num_params) 
     109 
     110supports_constraints = True 
     111 
     112def quote_name(name): 
     113    # the standard for firebird is not to quote names but in django 
     114    # it will quote all names uppercased so we can write sql without quotes 
     115    # because all names without quotes will defualt to uppercased, 
     116    # like oracle truncate names bigger than 30 chars 
     117    if not name.startswith('"') and not name.endswith('"'): 
     118        name = '"%s"' % util.truncate_name(name, get_max_name_length()) 
     119    return name.upper() 
     120 
     121_quote_sequence_name = lambda n: '"%s_SQ"' % util.truncate_name(n.upper(), get_max_name_length()-3) 
     122_quote_trigger_name = lambda n: '"%s_TR"' % util.truncate_name(n.upper(), get_max_name_length()-3) 
     123 
     124def dictfetchone(cursor): 
     125    "Returns a row from the cursor as a dict" 
     126    return cursor.fetchonemap() 
     127 
     128def dictfetchmany(cursor, number): 
     129    "Returns a certain number of rows from a cursor as a dict" 
     130    return cursor.fetchmanymap(number) 
     131 
     132def dictfetchall(cursor): 
     133    "Returns all rows from a cursor as a dict" 
     134    return cursor.fetchallmap() 
     135 
     136def get_last_insert_id(cursor, table_name, pk_name): 
     137    stmt = server_version < '2' and 'SELECT GEN_ID(%s, 0) FROM RDB$DATABASE' or 'NEXT VALUE FOR %s' 
     138    cursor.execute(stmt % _quote_sequence_name(table_name)) 
     139    return cursor.fetchone()[0] 
     140 
     141def get_date_extract_sql(lookup_type, column_name): 
     142    # lookup_type is 'year', 'month', 'day' 
     143    return "EXTRACT(%s FROM %s)" % (lookup_type.upper(), column_name) 
     144 
     145def get_date_trunc_sql(lookup_type, column_name): 
     146    if lookup_type == 'year': 
     147         sql = "EXTRACT(year FROM %s)||'-01-01 00:00:00'" % column_name 
     148    elif lookup_type == 'month': 
     149        sql = "EXTRACT(year FROM %s)||'-'||EXTRACT(month FROM %s)||'-01 00:00:00'" % (column_name, column_name) 
     150    elif lookup_type == 'day': 
     151        sql = "EXTRACT(year FROM %s)||'-'||EXTRACT(month FROM %s)||'-'||EXTRACT(day FROM %s)||' 00:00:00'" % (column_name, column_name, column_name) 
     152    return "CAST(%s AS TIMESTAMP)" % sql 
     153 
     154def get_datetime_cast_sql(): 
     155    return None 
     156 
     157def get_limit_offset_sql(limit, offset=None): 
     158    return "" 
     159 
     160def get_random_function_sql(): 
     161    return "RAND()" 
     162 
     163def get_deferrable_sql(): 
     164    # Not supported, maybe in Firebird 3.0 
     165    return "" 
     166 
     167def get_fulltext_search_sql(field_name): 
     168    # maybe in Firebird 3.0 
     169    raise NotImplementedError 
     170 
     171def get_drop_foreignkey_sql(): 
     172    return "DROP CONSTRAINT" 
     173 
     174def get_pk_default_value(): 
     175    return "NULL" 
     176 
     177def get_max_name_length(): 
     178    return 30 
     179 
     180def get_sequence_sql(style, table_name, column_name): 
     181    """To simulate auto-incrementing primary keys in Firebird, we have to 
     182    create a generator (sequence in Firebird 2) and a trigger. 
     183 
     184    Create the sequences and triggers names based only on table name 
     185    since django only support one auto field per model""" 
     186    KEYWORD = style.SQL_KEYWORD 
     187    TABLE = style.SQL_TABLE 
     188    FIELD = style.SQL_FIELD 
     189 
     190    sequence_name = _quote_sequence_name(table_name) 
     191    column_name = quote_name(column_name) 
     192    return ["%s %s;" % ( \ 
     193            KEYWORD(server_version < '2' and 'CREATE GENERATOR' or 'CREATE SEQUENCE'), 
     194            TABLE(sequence_name)), 
     195        "\n".join(["%s %s %s %s" % ( \ 
     196            KEYWORD('CREATE TRIGGER'), 
     197            TABLE(_quote_trigger_name(table_name)), 
     198            KEYWORD('FOR'), 
     199            TABLE(quote_name(table_name))), 
     200        "%s 0 %s" % ( \ 
     201            KEYWORD('ACTIVE BEFORE INSERT POSITION'), 
     202            KEYWORD('AS')), 
     203        KEYWORD('BEGIN'), 
     204        "  %s ((%s.%s %s) %s (%s.%s = 0)) %s" % ( \ 
     205            KEYWORD('IF'), 
     206            KEYWORD('NEW'), 
     207            FIELD(column_name), 
     208            KEYWORD('IS NULL'), 
     209            KEYWORD('OR'), 
     210            KEYWORD('NEW'), 
     211            FIELD(column_name), 
     212            KEYWORD('THEN')), 
     213        "  %s" % KEYWORD('BEGIN'), 
     214        "    %s.%s = %s(%s, 1);" % ( \ 
     215            KEYWORD('NEW'), 
     216            FIELD(column_name), 
     217            KEYWORD('GEN_ID'), 
     218            TABLE(sequence_name)), 
     219        "  %s" % KEYWORD('END'), 
     220        KEYWORD('END')])] 
     221 
     222def get_sql_flush(style, tables, sequences): 
     223    """Return a list of SQL statements required to remove all data from 
     224    all tables in the database (without actually removing the tables 
     225    themselves) and put the database in an empty 'initial' state 
     226 
     227    For Firebird we gonna take a dangerous workaround: 
     228        - first create a temporary table 'django_flush$constraints' that 
     229        will contain all Foreignkey definitions for this database. 
     230        - next import this definitions into the new table and delete them 
     231        from system table 'rdb$relation_constraints'. 
     232        - after the flush is done import the definitions back to the system table 
     233        and delete the temporary table. 
     234    """ 
     235    KEYWORD = style.SQL_KEYWORD 
     236    TABLE = style.SQL_TABLE 
     237    FIELD = style.SQL_FIELD 
     238 
     239    if tables: 
     240        temp_table_name = quote_name('django_flush$constraints') 
     241        orig_table_name = 'RDB$RELATION_CONSTRAINTS' 
     242        sql = ["\n".join([ 
     243            "%s %s (" % (KEYWORD('CREATE TABLE'), TABLE(temp_table_name)), 
     244            "  %s %s(31) %s," % (FIELD(quote_name('rdb$constraint_name')), KEYWORD('CHAR'), KEYWORD('CHARACTER SET UNICODE_FSS')), 
     245            "  %s %s(11)," % (FIELD(quote_name('rdb$constraint_type')), KEYWORD('CHAR')), 
     246            "  %s %s(31) %s," % (FIELD(quote_name('rdb$relation_name')), KEYWORD('CHAR'), KEYWORD('CHARACTER SET UNICODE_FSS')), 
     247            "  %s %s(3)," % (FIELD(quote_name('rdb$deferrable')), KEYWORD('CHAR')), 
     248            "  %s %s(3)," % (FIELD(quote_name('rdb$initially_deferred')), KEYWORD('CHAR')), 
     249            "  %s %s(31) %s" % (FIELD(quote_name('rdb$index_name')), KEYWORD('CHAR'), KEYWORD('CHARACTER SET UNICODE_FSS')), 
     250            ");"]), 
     251            "%s;" % KEYWORD('COMMIT'), 
     252            "%s %s %s %s %s %s %s %s = 'FOREIGN KEY';" % ( \ 
     253                KEYWORD('INSERT INTO'), TABLE(temp_table_name), 
     254                KEYWORD('SELECT'), FIELD('*'), KEYWORD('FROM'), TABLE(orig_table_name), 
     255                KEYWORD('WHERE'), FIELD('rdb$constraint_type')), 
     256            "%s %s %s %s = 'FOREIGN KEY';" % ( \ 
     257                KEYWORD('DELETE FROM'), TABLE(orig_table_name), 
     258                KEYWORD('WHERE'), FIELD('rdb$constraint_type')), 
     259            "%s;" % KEYWORD('COMMIT')] 
     260 
     261        sql += ['%s %s;' % \ 
     262                (KEYWORD('DELETE FROM'), 
     263                 TABLE(quote_name(table)) 
     264                 ) for table in tables] 
     265 
     266        sql += ["%s %s %s 0;" % \ 
     267                (KEYWORD(server_version < '2' and 'SET GENERATOR' or 'ALTER SEQUENCE'), 
     268                 TABLE(_quote_sequence_name(sequence['table'])), 
     269                 KEYWORD(server_version < '2' and 'TO' or 'RESTART WITH') 
     270                 ) for sequence in sequences] 
     271        return sql + [ 
     272            "%s %s %s %s %s %s;" % ( \ 
     273                KEYWORD('INSERT INTO'), TABLE(orig_table_name), 
     274                KEYWORD('SELECT'), FIELD('*'), KEYWORD('FROM'), TABLE(temp_table_name)), 
     275            "%s %s;" % (KEYWORD('DROP TABLE'), TABLE(temp_table_name)), 
     276            "%s;" % KEYWORD('COMMIT')] 
     277    return [] 
     278 
     279OPERATOR_MAPPING = { 
     280    'exact': '= %s', 
     281    'iexact': "= UPPER(%s)", 
     282    'contains': "LIKE %s ESCAPE '\\'", 
     283    'icontains': "LIKE UPPER(%s) ESCAPE '\\'", 
     284    'gt': '> %s', 
     285    'gte': '>= %s', 
     286    'lt': '< %s', 
     287    'lte': '<= %s', 
     288    'startswith': "LIKE %s ESCAPE '\\'", 
     289    'endswith': "LIKE %s ESCAPE '\\'", 
     290    'istartswith': "LIKE UPPER(%s) ESCAPE '\\'", 
     291    'iendswith': "LIKE UPPER(%s) ESCAPE '\\'", 
     292 
     293    'text_icontains': "CONTAINING %s", 
     294} 
  • django/db/backends/firebird/client.py

    old new  
     1from django.conf import settings 
     2import os 
     3 
     4def 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

    old new  
     1from django.db import transaction 
     2from django.db.backends.firebird.base import quote_name 
     3 
     4def get_table_list(cursor): 
     5    "Returns a list of table names in the current database." 
     6    cursor.execute(""" 
     7        SELECT rdb$relation_name FROM rdb$relations 
     8        WHERE rdb$system_flag = 0 AND rdb$view_blr IS NULL ORDER BY rdb$relation_name""") 
     9    return [str(row[0].strip().lower()) for row in cursor.fetchall()] 
     10 
     11def get_table_description(cursor, table_name): 
     12    "Returns a description of the table, with the DB-API cursor.description interface." 
     13    #cursor.execute("SELECT FIRST 1 * FROM %s" % quote_name(table_name)) 
     14    #return cursor.description 
     15    # (name, type_code, display_size, internal_size, precision, scale, null_ok) 
     16    cursor.execute(""" 
     17        SELECT DISTINCT R.RDB$FIELD_NAME AS FNAME, 
     18                  F.RDB$FIELD_TYPE AS FTYPE, 
     19                  F.RDB$FIELD_LENGTH AS FLENGTH, 
     20                  F.RDB$FIELD_PRECISION AS FPRECISION, 
     21                  F.RDB$FIELD_SCALE AS FSCALE, 
     22                  R.RDB$NULL_FLAG AS NULL_FLAG, 
     23                  R.RDB$FIELD_POSITION 
     24        FROM RDB$RELATION_FIELDS R 
     25             JOIN RDB$FIELDS F ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME 
     26        WHERE F.RDB$SYSTEM_FLAG=0 and R.RDB$RELATION_NAME= %s 
     27        ORDER BY R.RDB$FIELD_POSITION 
     28    """, (table_name,)) 
     29    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()] 
     30 
     31 
     32def get_relations(cursor, table_name): 
     33    """ 
     34    Returns a dictionary of {field_index: (field_index_other_table, other_table)} 
     35    representing all relationships to the given table. Indexes are 0-based. 
     36    """ 
     37    cursor.execute(""" 
     38        SELECT seg.rdb$field_name, seg_ref.rdb$field_name, idx_ref.rdb$relation_name 
     39        FROM rdb$indices idx 
     40        INNER JOIN rdb$index_segments seg 
     41            ON seg.rdb$index_name = idx.rdb$index_name 
     42        INNER JOIN rdb$indices idx_ref 
     43            ON idx_ref.rdb$index_name = idx.rdb$foreign_key 
     44        INNER JOIN rdb$index_segments seg_ref 
     45            ON seg_ref.rdb$index_name = idx_ref.rdb$index_name 
     46        WHERE idx.rdb$relation_name = %s 
     47            AND idx.rdb$foreign_key IS NOT NULL""", [table_name]) 
     48 
     49    relations = {} 
     50    for row in cursor.fetchall(): 
     51        relations[row[0].rstrip()] = (row[1].strip(), row[2].strip()) 
     52    return relations 
     53 
     54def get_indexes(cursor, table_name): 
     55    """ 
     56    Returns a dictionary of fieldname -> infodict for the given table, 
     57    where each infodict is in the format: 
     58        {'primary_key': boolean representing whether it's the primary key, 
     59         'unique': boolean representing whether it's a unique index} 
     60    """ 
     61 
     62    # This query retrieves each field name and index type on the given table. 
     63    cursor.execute(""" 
     64        SELECT seg.rdb$field_name, const.rdb$constraint_type 
     65        FROM rdb$relation_constraints const 
     66        LEFT JOIN rdb$index_segments seg 
     67            ON seg.rdb$index_name = const.rdb$index_name 
     68        WHERE const.rdb$relation_name = %s 
     69            AND (const.rdb$constraint_type = 'PRIMARY KEY' 
     70                OR const.rdb$constraint_type = 'UNIQUE')""", [table_name]) 
     71    indexes = {} 
     72    for row in cursor.fetchall(): 
     73        indexes[row[0].strip()] = { 
     74            'primary_key': ('PRIMARY KEY' == row[1].strip()), 
     75            'unique': ('UNIQUE' == row[1].strip())} 
     76    return indexes 
     77 
     78# Maps type codes to Django Field types. 
     79# !todo 
     80DATA_TYPES_REVERSE = { 
     81    7: 'BooleanField', 
     82    7: 'SmallIntegerField', 
     83    8: 'IntegerField', 
     84    261: 'TextField', 
     85    37: 'IPAddressField', 
     86    37: 'CharField', 
     87    12: 'DateField', 
     88    13: 'TimeField', 
     89    35: 'DateTimeField', 
     90    10: 'FloatField', 
     91} 
  • django/db/backends/firebird/creation.py

    old new  
     1from django.core import management 
     2import sys, os, time 
     3 
     4# This dictionary maps Field objects to their associated PostgreSQL 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. 
     8 
     9DATA_TYPES = { 
     10    'AutoField':                     'INTEGER', 
     11    'BooleanField':                  'SMALLINT', 
     12    'CharField':                     'VARCHAR(%(maxlength)s)', 
     13    'CommaSeparatedIntegerField':    'VARCHAR(%(maxlength)s)', 
     14    'DateField':                     'DATE', 
     15    'DateTimeField':                 'TIMESTAMP', 
     16    'FileField':                     'VARCHAR(100)', 
     17    'FilePathField':                 'VARCHAR(100)', 
     18    'FloatField':                    'NUMERIC(%(max_digits)s, %(decimal_places)s)', 
     19    'ImageField':                    'VARCHAR(100)', 
     20    'IntegerField':                  'INTEGER', 
     21    'IPAddressField':                'VARCHAR(15)', 
     22    'ManyToManyField':               None, 
     23    'NullBooleanField':              'SMALLINT', 
     24    'OneToOneField':                 'INTEGER', 
     25    'PhoneNumberField':              'VARCHAR(20)', 
     26    'PositiveIntegerField':          'INTEGER', 
     27    'PositiveSmallIntegerField':     'SMALLINT', 
     28    'SlugField':                     'VARCHAR(%(maxlength)s)', 
     29    'SmallIntegerField':             'SMALLINT', 
     30    'TextField':                     'BLOB SUB_TYPE TEXT', 
     31    'TimeField':                     'TIME', 
     32    'URLField':                      'VARCHAR(200)', 
     33    'USStateField':                  'VARCHAR(2)', 
     34} 
     35 
     36TEST_DATABASE_PREFIX = 'test_' 
     37 
     38def create_test_db(settings, connection, backend, verbosity, autoclobber): 
     39 
     40    if verbosity >= 1: 
     41        print "Creating test database..." 
     42 
     43    if settings.TEST_DATABASE_NAME: 
     44        if os.path.isfile(settings.DATABASE_NAME): 
     45            TEST_DATABASE_NAME = os.path.join( 
     46                os.path.dirname(settings.DATABASE_NAME), 
     47                settings.TEST_DATABASE_NAME) 
     48        else: 
     49            import tempfile 
     50            tempfile.gettempdir() 
     51            TEST_DATABASE_NAME = os.path.join( 
     52                tempfile.gettempdir(), 
     53                settings.TEST_DATABASE_NAME) 
     54    else: 
     55        if os.path.isfile(settings.DATABASE_NAME): 
     56            TEST_DATABASE_NAME = os.path.join( 
     57                os.path.dirname(settings.DATABASE_NAME), 
     58                TEST_DATABASE_PREFIX + os.path.basename(settings.DATABASE_NAME)) 
     59        else: 
     60            import tempfile 
     61            tempfile.gettempdir() 
     62            TEST_DATABASE_NAME = os.path.join( 
     63                tempfile.gettempdir(), 
     64                TEST_DATABASE_PREFIX + settings.DATABASE_NAME) 
     65 
     66    settings.DATABASE_NAME = TEST_DATABASE_NAME 
     67 
     68    try: 
     69        _create_test_db(backend, settings) 
     70    except Exception, e: 
     71        sys.stderr.write("Got an error creating the test database: %s\n" % e) 
     72        if not autoclobber: 
     73            confirm = raw_input("It appears the test database, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % TEST_DATABASE_NAME) 
     74        if autoclobber or confirm == 'yes': 
     75            try: 
     76                if verbosity >= 1: 
     77                    print "Destroying old test database..." 
     78                _destroy_test_db(connection) 
     79                if verbosity >= 1: 
     80                    print "Creating test database..." 
     81                _create_test_db(backend, settings) 
     82            except Exception, e: 
     83                sys.stderr.write("Got an error recreating the test database: %s\n" % e) 
     84                sys.exit(2) 
     85        else: 
     86            print "Tests cancelled." 
     87            sys.exit(1) 
     88 
     89    management.syncdb(verbosity, interactive=False) 
     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 
     96def destroy_test_db(settings, connection, backend, old_database_name, verbosity): 
     97    if verbosity >= 1: 
     98        print "Destroying test database..." 
     99 
     100    # To avoid "database is being accessed by other users" errors. 
     101    time.sleep(1) 
     102    _destroy_test_db(connection) 
     103 
     104def _create_test_db(backend, settings): 
     105    connection = backend.Database.create_database(""" 
     106        CREATE DATABASE '%s' user '%s' password '%s'""" % \ 
     107        (settings.DATABASE_NAME, settings.DATABASE_USER, settings.DATABASE_PASSWORD)) 
     108    cursor = connection.cursor() 
     109    cursor.execute(""" 
     110    DECLARE EXTERNAL FUNCTION rand 
     111        RETURNS DOUBLE PRECISION 
     112        BY VALUE ENTRY_POINT 'IB_UDF_rand' MODULE_NAME 'ib_udf'; 
     113    """) 
     114    connection.commit() 
     115    connection.close() 
     116 
     117def _destroy_test_db(connection): 
     118    cursor = connection.cursor() 
     119    connection.connection.drop_database() 
     120    connection.connection = None 
  • django/core/management.py

    old new  
    159159    Returns list_of_sql, pending_references_dict 
    160160    """ 
    161161    from django.db import backend, get_creation_module, models 
     162    from django.conf import settings 
    162163    data_types = get_creation_module().DATA_TYPES 
    163164 
    164165    opts = model._meta 
     
    177178            # Make the definition (e.g. 'foo VARCHAR(30)') for this field. 
    178179            field_output = [style.SQL_FIELD(backend.quote_name(f.column)), 
    179180                style.SQL_COLTYPE(col_type % rel_field.__dict__)] 
    180             field_output.append(style.SQL_KEYWORD('%sNULL' % (not f.null and 'NOT ' or ''))) 
     181            column_null_sql = '%sNULL' % (not f.null and 'NOT ' or '') 
     182            if settings.DATABASE_ENGINE == 'firebird' and f.null: 
     183                column_null_sql = (not f.null or f.primary_key) and 'NOT NULL' or '' 
     184            if column_null_sql: 
     185                field_output.append(style.SQL_KEYWORD(column_null_sql)) 
    181186            if f.unique: 
    182187                field_output.append(style.SQL_KEYWORD('UNIQUE')) 
    183188            if f.primary_key: 
     
    207212        full_statement.append('    %s%s' % (line, i < len(table_output)-1 and ',' or '')) 
    208213    full_statement.append(');') 
    209214    final_output.append('\n'.join(full_statement)) 
     215     
     216    if opts.has_auto_field and hasattr(backend, 'get_sequence_sql'): 
     217        final_output += backend.get_sequence_sql(style, opts.db_table, opts.pk.column) 
    210218 
    211219    return final_output, pending_references 
    212220 
     
    231239                # So we are careful with character usage here. 
    232240                r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table)))) 
    233241                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
     242                    (backend.quote_name(r_table), backend.quote_name(r_name)
    235243                    backend.quote_name(r_col), backend.quote_name(table), backend.quote_name(col),  
    236244                    backend.get_deferrable_sql())) 
    237245            del pending_references[model] 
     
    273281                style.SQL_FIELD(backend.quote_name(f.m2m_reverse_name())))) 
    274282            table_output.append(');') 
    275283            final_output.append('\n'.join(table_output)) 
     284            if hasattr(backend, 'get_sequence_sql'): 
     285                final_output += backend.get_sequence_sql(style, f.m2m_db_table(), 'id') 
    276286    return final_output 
    277287 
    278288def get_sql_delete(app): 
     
    456466            unique = f.unique and 'UNIQUE ' or '' 
    457467            output.append( 
    458468                style.SQL_KEYWORD('CREATE %sINDEX' % unique) + ' ' + \ 
    459                 style.SQL_TABLE('%s_%s' % (model._meta.db_table, f.column)) + ' ' + \ 
     469                style.SQL_TABLE(backend.quote_name('%s_%s' % (model._meta.db_table, f.column))) + ' ' + \ 
    460470                style.SQL_KEYWORD('ON') + ' ' + \ 
    461471                style.SQL_TABLE(backend.quote_name(model._meta.db_table)) + ' ' + \ 
    462472                "(%s);" % style.SQL_FIELD(backend.quote_name(f.column)) 
  • django/contrib/redirects/models.py

    old new  
    44 
    55class Redirect(models.Model): 
    66    site = models.ForeignKey(Site, radio_admin=models.VERTICAL) 
    7     old_path = models.CharField(_('redirect from'), maxlength=200, db_index=True, 
     7    old_path = models.CharField(_('redirect from'), maxlength=100, db_index=False, 
    88        help_text=_("This should be an absolute path, excluding the domain name. Example: '/events/search/'.")) 
    9     new_path = models.CharField(_('redirect to'), maxlength=200, blank=True, 
     9    new_path = models.CharField(_('redirect to'), maxlength=100, blank=True, 
    1010        help_text=_("This can be either an absolute path (as above) or a full URL starting with 'http://'.")) 
    1111 
    1212    class Meta: