Ticket #10096: added linter backend.diff

File added linter backend.diff, 26.9 KB (added by chernyshov, 14 years ago)

added LINTER backend for Django

  • django/db/backends/linter/base.py

     
     1"""
     2LINTER database backend for Django.
     3"""
     4from django.db.backends import *
     5                                       
     6from django.db.backends.linter import query
     7from django.db.backends.linter.client import DatabaseClient
     8from django.db.backends.linter.creation import DatabaseCreation
     9from django.db.backends.linter.introspection import DatabaseIntrospection
     10from django.utils.encoding import smart_str, force_unicode
     11
     12try:
     13    import LinPy as Database
     14except ImportError, e:
     15    from django.core.exceptions import ImproperlyConfigured
     16    raise ImproperlyConfigured, "Error loading LinPy module: %s" % e
     17
     18DatabaseError = Database.Error
     19IntegrityError = Database.IntegrityError
     20
     21class DatabaseFeatures(BaseDatabaseFeatures):
     22    uses_custom_query_class = True
     23   
     24class DatabaseOperations(BaseDatabaseOperations):
     25
     26    _lookup_types_dict = {'day' : 'D', 'month' : 'M', 'year' : 'Y'}
     27
     28    def date_extract_sql(self, lookup_type, table_name):     
     29        return "DATESPLIT (%s, '%s')" % (table_name, self._lookup_types_dict[lookup_type])
     30
     31    def date_trunc_sql(self, lookup_type, field_name):
     32        return "TRUNC(%s, '%s')" % (field_name, self._lookup_types_dict[lookup_type])
     33
     34    def drop_foreignkey_sql(self):
     35        return "DROP FOREIGN KEY"
     36
     37    def fulltext_search_sql(self, field_name):
     38        return "%s CONTAINS '%%s'" % field_name
     39
     40    def last_executed_query(self, cursor, sql, params):
     41        """
     42        Returns a string of the query last executed by the given cursor, with
     43        placeholders replaced with actual values.
     44        """
     45        from django.utils.encoding import smart_unicode, force_unicode
     46
     47        if not params:
     48            return smart_unicode(sql)
     49
     50        # Convert params to contain Unicode values.
     51        to_unicode = lambda s: force_unicode(s, strings_only=True)
     52        if isinstance(params, (list, tuple)):
     53            u_params = tuple([to_unicode(val) for val in params])
     54        else:
     55            u_params = dict([(to_unicode(k), to_unicode(v)) for k, v in params.items()])
     56
     57        return smart_unicode(sql) % u_params
     58
     59    def last_insert_id(self, cursor, table_name, pk_name):
     60        query = "SELECT %s FROM %s WHERE ROWID = LAST_ROWID" % (self.quote_name(pk_name), self.quote_name(table_name)) # 23.09.
     61        cursor.execute(query)
     62        return cursor.fetchone()[0]
     63
     64    def lookup_cast(self, lookup_type):
     65        if lookup_type in ('iexact', 'icontains', 'iregex', 'istartswith', 'iendswith'):
     66            return "UPPER(%s)"
     67        return "%s"
     68
     69    def no_limit_value(self):
     70        return -1
     71
     72    def query_class(self, DefaultQueryClass):
     73        return query.query_class(DefaultQueryClass, Database)
     74
     75    def quote_name(self, name):   
     76        if name.startswith('"') and name.endswith('"'):
     77            return name # Quoting once is enough.
     78        return '"%s"' % name.upper()
     79   
     80    def random_function_sql(self):
     81        return "RAND()"
     82
     83    def sql_flush(self, style, tables, sequences): 
     84        # Return a list of 'TRUNCATE x;', 'TRUNCATE y;',
     85        # 'TRUNCATE z;'... style SQL statements         
     86       
     87        sql = ['%s %s %s;' % \
     88                (style.SQL_KEYWORD('TRUNCATE'),
     89                 style.SQL_KEYWORD('TABLE'),
     90                 style.SQL_FIELD(self.quote_name(table))
     91                 )  for table in tables]
     92        return sql
     93
     94class DatabaseWrapper(BaseDatabaseWrapper):
     95
     96    operators = {
     97        'exact': '= %s',
     98        'iexact': '= UPPER(%s)',
     99        'contains': 'LIKE %s',
     100        'icontains': 'LIKE UPPER(%s)',
     101        'regex': 'SIMILAR TO %s',
     102        'iregex': 'SIMILAR TO UPPER(%s)',
     103        'gt': '> %s',
     104        'gte': '>= %s',
     105        'lt': '< %s',
     106        'lte': '<= %s',
     107        'startswith': 'LIKE %s',
     108        'endswith': 'LIKE %s',                                 
     109        'istartswith': 'LIKE UPPER(%s)',
     110        'iendswith': 'LIKE UPPER(%s)',
     111    }
     112   
     113    def __init__(self, **kwargs):
     114        super(DatabaseWrapper, self).__init__(**kwargs)
     115
     116        self.features = DatabaseFeatures()   
     117        self.ops = DatabaseOperations()
     118        self.client = DatabaseClient()
     119        self.creation = DatabaseCreation(self)
     120        self.introspection = DatabaseIntrospection(self)
     121        self.validation = BaseDatabaseValidation()
     122
     123    def _valid_connection(self):
     124        return self.connection is not None
     125
     126    def _cursor(self, settings):
     127        # SetUnicodeData(1) - set output data mode in unicode
     128        Database.SetUnicodeData(1)
     129        from django.conf import settings
     130
     131        if not self._valid_connection():
     132            self.connection = Database.connect(settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME, **self.options)
     133        cursor = self.connection.cursor(mode=Database.M_EXCLUSIVE)   
     134        cursor = LinterCursorWrapper(cursor)
     135        return cursor
     136
     137    def _commit(self):
     138        if self.connection is not None:
     139            self.connection.commit()
     140                       
     141    def _rollback(self):
     142        if self.connection is not None:
     143            try:
     144                self.connection.rollback()
     145            except Database.NotSupportedError:
     146                pass
     147
     148    def set_date_emulation(self, value=0):
     149        # Set mode conversion values datetime type to date type,
     150        # if data contain values only for year, month and day.
     151        # By default always returned data in datetime type.
     152        Database.SetDateEmulation(value)
     153
     154class LinterCursorWrapper(object):
     155    """
     156    Django uses "format" style placeholders, but LinPy uses "qmark" style.
     157    This fixes it -- but note that if you want to use a literal "%s" in a query,
     158    you'll need to use "%%s".
     159    """
     160    def __init__(self, cursor):
     161        self.cursor = cursor
     162                                         
     163    def __getattr__(self, attr):
     164        if self.__dict__.has_key(attr):
     165            return self.__dict__[attr]
     166        else:
     167            return getattr(self.cursor, attr)
     168
     169    def execute(self, query, params=()):
     170        query = self.convert_query(query, len(params))
     171
     172        try:
     173            return self.cursor.execute(query, params)   
     174        except DatabaseError, e:
     175            if type(e) != IntegrityError:
     176                e = IntegrityError(e)
     177        raise e
     178
     179    def executemany(self, query, param_list):
     180        try:
     181            query = self.convert_query(query, len(param_list[0]))
     182            return self.cursor.executemany(query, param_list)
     183        except (IndexError,TypeError):
     184            # No parameter list provided
     185            return None
     186                                         
     187    def convert_query(self, query, num_params):
     188        if num_params:
     189            return smart_str(query % tuple("?" * num_params))
     190        else:     
     191            return smart_str(query)
  • django/db/backends/linter/client.py

     
     1from django.db.backends import BaseDatabaseClient
     2from django.conf import settings
     3import os
     4
     5class DatabaseClient(BaseDatabaseClient):
     6    def runshell(self):
     7        args = ['']
     8        if settings.DATABASE_PASSWORD:
     9            args = ["-u %s/%s" % (settings.DATABASE_USER, settings.DATABASE_PASSWORD)]
     10        else:
     11            args = ["-u %s/" % settings.DATABASE_USER]
     12        args += [" -n %s" % settings.DATABASE_NAME]
     13        os.execvp('inl', args)
     14
     15
  • django/db/backends/linter/introspection.py

     
     1from django.db.backends import BaseDatabaseIntrospection
     2import string
     3
     4class DatabaseIntrospection(BaseDatabaseIntrospection):
     5    # Maps type codes to Django Field types.
     6    data_types_reverse = {
     7        'CHAR': 'CharField',
     8        'NCHAR': 'CharField',
     9        'VARCHAR': 'CharField',   
     10        'NACHAR VARYING': 'CharField',
     11        'SMALLINT': 'SmallIntegerField',
     12        'INTEGER': 'IntegerField',
     13        'BIGINT': 'IntegerField',
     14        'REAL': 'FloatField',
     15        'DOUBLE': 'FloatField',
     16        'NUMERIC': 'FloatField',
     17        'BOOLEAN': 'BooleanField',
     18        'DATE': 'DateField',
     19        'DATE': 'DateFieldWrapper',
     20        'BLOB': 'TextField',
     21        'EXTFILE': 'CharField',
     22    }
     23
     24    def get_table_list(self, cursor):
     25        "Returns a list of table names in the current database."
     26        cursor.execute("""
     27            SELECT TABLE_NAME 
     28            FROM LINTER_SYSTEM_USER.TABLES
     29            WHERE TABLE_SCHEM = USER AND TABLE_TYPE ='TABLE'
     30            AND TABLE_NAME NOT LIKE '$$$%' AND TABLE_NAME NOT LIKE 'L\_%'
     31            AND TABLE_NAME NOT IN ('SERVERS','PRIV_TYPES','TYPEINFO','COUNTER6',
     32            'COUNTER8','COUNTER31','PROVIDER_TYPES','ERRORS')""")
     33        return ([string.lower(row[0]) for row in cursor.fetchall()])
     34
     35    def get_table_description(self, cursor, table_name):
     36        qn = self.connection.ops.quote_name
     37        cursor.execute("SELECT * FROM %s LIMIT 1" % qn(table_name))
     38        return cursor.description
     39
     40    def _name_to_index(self, cursor, table_name):
     41        """
     42        Returns a dictionary of {field_name: field_index} for the given table.
     43        Indexes are 0-based.
     44        """
     45        return dict([(d[0], i) for i, d in enumerate(self.get_table_description(cursor, table_name))])
     46
     47    def get_relations(self, cursor, table_name):
     48        """
     49        Returns a dictionary of {field_index: (field_index_other_table, other_table)}
     50        representing all relationships to the given table. Indexes are 0-based.
     51        """
     52        my_field_dict = self._name_to_index(cursor, table_name)
     53        relations = {}
     54
     55        cursor.execute("""
     56            SELECT FKCOLUMN_NAME, PKTABLE_NAME, PKCOLUMN_NAME
     57            FROM LINTER_SYSTEM_USER.FOREIGN_KEYS
     58            WHERE FKTABLE_NAME = %s""" % dbo.quote_name(table_name))
     59        for row in cursor.fetchall():
     60            other_field_index = self._name_to_index(cursor, row[1])[row[2]]
     61            my_field_index = my_field_dict[row[0]]
     62            relations[my_field_index] = (other_field_index, row[1])
     63
     64        return relations       
     65
     66    def get_indexes(self, cursor, table_name):
     67        """
     68        Returns a dictionary of fieldname -> infodict for the given table,
     69        where each infodict is in the format:
     70            {'primary_key': boolean representing whether it's the primary key,
     71             'unique': boolean representing whether it's a unique index}
     72        """
     73        indexes = {}
     74     
     75        cursor.execute("""
     76            SELECT NON_UNIQUE, COLUMN_NAME
     77            FROM LINTER_SYSTEM_USER.TABLESTATISTICS
     78            WHERE TABLE_NAME = %s""" % dbo.quote_name(table_name))
     79        for row in cursor.fetchall():
     80            if row[0] != None:
     81                indexes[row[1]] = {'primary_key': bool(row[1]), 'unique': not bool(row[0])}
     82
     83        return indexes
     84
  • django/db/backends/linter/creation.py

     
     1import sys
     2from django.conf import settings
     3from django.db.backends.creation import BaseDatabaseCreation
     4
     5TEST_USER_PREFIX = 'TEST_'
     6
     7class DatabaseCreation(BaseDatabaseCreation):
     8    # This dictionary maps Field objects to their associated LINTER column
     9    # types, as strings. Column-type strings can contain format strings; they'll
     10    # be interpolated against the values of Field.__dict__ before being output.
     11    # If a column type is set to None, it won't be included in the output.
     12    data_types = {
     13        'AutoField':                    'integer AUTOINC',
     14        'BooleanField':                 'boolean',
     15        'CharField':                    'nvarchar(%(max_length)s)',
     16        'CommaSeparatedIntegerField':   'varchar(%(max_length)s)',
     17        'DateField':                    'date',
     18        'DateTimeField':                'date',
     19        'DecimalField':                 'number(%(max_digits)s, %(decimal_places)s)',
     20        'FileField':                    'varchar(%(max_length)s)',
     21        'FilePathField':                'varchar(%(max_length)s)',
     22        'FloatField':                   'double',
     23        'IntegerField':                 'integer',
     24        'IPAddressField':               'char(15)',
     25        'NullBooleanField':             'integer',
     26        'OneToOneField':                'integer',
     27        'PositiveIntegerField':         'integer',
     28        'PositiveSmallIntegerField':    'smallint',
     29        'SlugField':                    'varchar(%(max_length)s)',
     30        'SmallIntegerField':            'smallint',
     31        'TextField':                    'varchar(1000)',   
     32        'TimeField':                    'date',
     33        'URLField':                     'varchar(%(max_length)s)',
     34    }
     35
     36    remember = {}
     37
     38    def _create_test_db(self, verbosity, autoclobber):
     39        """
     40        We don't created test database, we only create test user
     41        """
     42
     43        TEST_DATABASE_USER = TEST_USER_PREFIX + settings.DATABASE_USER
     44        TEST_DATABASE_PASSWD = settings.DATABASE_PASSWORD
     45
     46        parameters = {
     47            'user' : TEST_DATABASE_USER,
     48            'password' : TEST_DATABASE_PASSWD,
     49        }
     50
     51        self.remember['user'] = settings.DATABASE_USER
     52        self.remember['passwd'] = settings.DATABASE_PASSWORD
     53
     54        cursor = self.connection.cursor()
     55
     56        if verbosity >= 1:
     57            print "Creating test user..."
     58        try:
     59            self._create_test_user(cursor, parameters, verbosity)
     60        except Exception, e:
     61            sys.stderr.write("Got an error creating the test user: %s\n" % e)
     62            if not autoclobber:
     63                confirm = raw_input("It appears the test user, %s, already exists. Type 'yes'  to delete it? or 'no' to cancel: " % TEST_DATABASE_USER)
     64            if autoclobber or confirm == 'yes':
     65                try:
     66                    if verbosity >= 1:
     67                        print "Destroying old test user..."
     68                    self._destroy_test_user(cursor, parameters, verbosity)
     69                    if verbosity >= 1:
     70                        print "Creating test user..."
     71                    self._create_test_user(cursor, parameters, verbosity) 
     72                except Exception, e:
     73                    sys.stderr.write("Got an error recreating the test user: %s\n" % e)
     74                    sys.exit(2)
     75            else:
     76                print "Tests cancelled."
     77                sys.exit(1)
     78
     79        settings.DATABASE_USER = TEST_DATABASE_USER
     80
     81        return settings.DATABASE_NAME
     82
     83    def _destroy_test_db(self, test_database_name, verbosity):
     84        """
     85        Don't destroy database. Desrtoy test user.
     86        """
     87        TEST_DATABASE_USER = settings.DATABASE_USER
     88        TEST_DATABASE_PASSWD = settings.DATABASE_PASSWORD
     89
     90        parameters = {
     91            'user' : TEST_DATABASE_USER,
     92            'password' : TEST_DATABASE_PASSWD
     93        }
     94
     95        settings.DATABASE_USER = self.remember['user']
     96        settings.DATABASE_PASSWORD = self.remember['passwd']
     97
     98        cursor = self.connection.cursor()
     99
     100        if verbosity >= 1:
     101            print "Destroying test user..."
     102        self._destroy_test_user(cursor, parameters, verbosity)
     103       
     104        self.connection.close()
     105
     106    def _create_test_user(self, cursor, parameters, verbosity):
     107        if verbosity >= 2:
     108            print "_crete_test_user(): username = %s" % parameters['user']
     109        statements = [
     110            "CREATE USER %(user)s IDENTIFIED BY '%(password)s'",
     111            "GRANT RESOURCE TO %(user)s"
     112        ]
     113        self._execute_statements(cursor, statements, parameters, verbosity)
     114   
     115    def _destroy_test_user(self, cursor, parameters, verbosity):
     116        if verbosity >= 2:
     117            print "_destroy_test_user(): user = %s" % parameters['user']
     118        statements = ["DROP USER %(user)s CASCADE"]
     119       
     120        self._execute_statements(cursor, statements, parameters, verbosity)
     121           
     122    def _execute_statements(self, cursor, statements, parameters, verbosity):
     123        for template in statements:
     124            stmt = template % parameters
     125            if verbosity >= 2:
     126                print stmt
     127            try:
     128                cursor.execute(stmt)
     129            except Exception, err:
     130                sys.stderr.write("Failed (%s)\n" % (err))
     131                raise
     132
     133    def sql_for_pending_references(self, model, style, pending_references):
     134        """
     135        Returns any ALTER TABLE statements to add constraints after the fact.
     136        """                                                                 
     137        qn = self.connection.ops.quote_name
     138        final_output = []
     139        opts = model._meta
     140        if model in pending_references:
     141            for rel_class, f in pending_references[model]:
     142                rel_opts = rel_class._meta
     143                r_table = rel_opts.db_table
     144                r_col = f.column
     145                table = opts.db_table
     146                col = opts.get_field(f.rel.field_name).column
     147                final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % \
     148                    (qn(r_table),
     149                    qn(r_col), qn(table), qn(col),
     150                    self.connection.ops.deferrable_sql()))
     151            del pending_references[model]
     152        return final_output
     153
     154    def sql_indexes_for_field(self, model, f, style):
     155        """
     156        Return the CREATE INDEX SQL statements for a single model field
     157        """
     158        from django.db.models.fields.related import ForeignKey
     159        # LINTER create index for primary keys, unique and foreign keys
     160        # automatically
     161        if f.db_index and not f.unique and (not isinstance(f, ForeignKey)):
     162            qn = self.connection.ops.quote_name
     163            tablespace = f.db_tablespace or model._meta.db_tablespace
     164            if tablespace:
     165                sql = self.connection.ops.tablespace_sql(tablespace)
     166                if sql:
     167                    tablespace_sql = ' ' + sql
     168                else:
     169                    tablespace_sql = ''
     170            else:
     171                tablespace_sql = ''
     172            output = [style.SQL_KEYWORD('CREATE INDEX') + ' ' +
     173                style.SQL_TABLE(qn('%s_%s' % (model._meta.db_table, f.column))) + ' ' +
     174                style.SQL_KEYWORD('ON') + ' ' +
     175                style.SQL_TABLE(qn(model._meta.db_table)) + ' ' +
     176                "(%s)" % style.SQL_FIELD(qn(f.column)) +
     177                "%s;" % tablespace_sql]
     178        else:
     179            output = []
     180        return output           
     181
     182    def sql_remove_table_constraints(self, model, references_to_delete, style):
     183        from django.db.backends.util import truncate_name
     184
     185        output = []
     186        qn = self.connection.ops.quote_name
     187        for rel_class, f in references_to_delete[model]:
     188            table = rel_class._meta.db_table
     189            col = f.column
     190            output.append('%s %s %s (%s);' % \
     191                (style.SQL_KEYWORD('ALTER TABLE'),
     192                style.SQL_TABLE(qn(table)),
     193                style.SQL_KEYWORD(self.connection.ops.drop_foreignkey_sql()),
     194                style.SQL_FIELD(col)))
     195        del references_to_delete[model]
     196        return output
  • django/db/backends/linter/query.py

     
     1"""
     2Custom Query class for Linter.
     3Derives from: django.db.models.sql.query.Query
     4"""
     5
     6import datetime
     7
     8from django.db.backends import util
     9
     10# Cache. Maps default query class to new Linter query class.
     11_classes = {}
     12
     13def query_class(QueryClass, Database):
     14    """
     15    Returns a custom django.db.models.sql.query.Query subclass that is
     16    appropriate for Linter.
     17
     18    """
     19    global _classes
     20    try:
     21        return _classes[QueryClass]
     22    except KeyError:
     23        pass
     24
     25    class LinterQuery(QueryClass):
     26
     27        def as_sql(self, with_limits=True, with_col_aliases=False):
     28            """
     29            Creates the SQL for this query. Returns the SQL string and list
     30            of parameters.  This is overriden from the original Query class
     31            to accommodate Linter's limit/offset SQL.
     32
     33            If 'with_limits' is False, any limit/offset information is not
     34            included in the query.
     35            """
     36
     37            # The `do_offset` flag indicates whether we need to construct
     38            # the SQL needed to use limit/offset.       
     39            do_offset = with_limits and (self.high_mark is not None
     40                                         or self.low_mark)
     41
     42            # If no offsets, just return the result of the base class
     43            # `as_sql`.
     44            if not do_offset:
     45                return super(LinterQuery, self).as_sql(with_limits=False,
     46                        with_col_aliases=with_col_aliases)
     47
     48            # `get_columns` needs to be called before `get_ordering` to
     49            # populate `_select_alias`.
     50            self.pre_sql_setup()
     51            out_cols = self.get_columns()
     52            ordering = self.get_ordering()
     53
     54            sql, params = super(LinterQuery, self).as_sql(with_limits=False,
     55                    with_col_aliases=True)
     56
     57            # Constructing the result SQL, using the initial select SQL
     58            # obtained above.
     59            result =['%s' % sql]     
     60
     61            if self.low_mark:
     62                if self.high_mark == self.low_mark:
     63                    return None
     64                elif self.high_mark is not None:
     65                    result.append('LIMIT %d, %d' % (self.low_mark, (self.high_mark - self.low_mark)))
     66                else:
     67                    val = self.connection.ops.no_limit_value()
     68                    if val:
     69                        result.append('LIMIT %d, %d' % (self.low_mark, val))
     70            else:
     71                result.append('LIMIT %d' % self.high_mark)     
     72
     73            # Returning the SQL w/params.
     74            return ' '.join(result), params
     75
     76    _classes[QueryClass] = LinterQuery
     77    return LinterQuery
  • docs/faq/install.txt

     
    3030
    3131If you want to use Django with a database, which is probably the case, you'll
    3232also need a database engine. PostgreSQL_ is recommended, because we're
    33 PostgreSQL fans, and MySQL_, `SQLite 3`_, and Oracle_ are also supported.
     33PostgreSQL fans, and MySQL_, `SQLite 3`_, Oracle_, and LINTER_ are also supported.
    3434
    3535.. _Python: http://www.python.org/
    3636.. _Apache 2: http://httpd.apache.org/
     
    4040.. _MySQL: http://www.mysql.com/
    4141.. _`SQLite 3`: http://www.sqlite.org/
    4242.. _Oracle: http://www.oracle.com/
     43.. _LINTER: http://www.lintersql.com/
    4344
    4445Do I lose anything by using Python 2.3 versus newer Python versions, such as Python 2.5?
    4546----------------------------------------------------------------------------------------
  • docs/ref/databases.txt

     
    460460    Oracle. A workaround to this is to keep ``TextField`` columns out of any
    461461    models that you foresee performing ``distinct()`` queries on, and to
    462462    include the ``TextField`` in a related model instead.
     463
     464.. _linter-notes:
     465
     466.. versionadded:: 1.0
     467
     468LINTER notes
     469============
     470
     471Django supports `DBMS LINTER`_ versions 5.9 and higher. For working Django
     472with LINTER you will need the `LinPy.dll`. It's library based on
     473`Python Database API Specification v2.0`_ included in distributive `LINTER`
     474and supports Python versions 2.1-2.6.
     475
     476.. _`DBMS LINTER`: http://www.lintersql.com/
     477.. _`Python Database API Specification v2.0`: http://www.python.org/dev/peps/pep-0249/
     478
     479In order for the ``python manage.py syncdb`` command to work, your LINTER
     480database user must have access category ``resource`` or ``dba``.
     481To run Django's test suite, the user needs access category ``dba``.
     482   
     483Connecting to the database
     484--------------------------
     485
     486Your Django settings.py file should look something like this for LINTER::
     487
     488    DATABASE_ENGINE = 'linter'
     489    DATABASE_NAME = 'DEMO'
     490    DATABASE_USER = 'a_user'
     491    DATABASE_PASSWORD = 'a_password'
     492    DATABASE_HOST = ''
     493    DATABASE_PORT = ''
     494
     495``DateField`` and ``DateTimeField`` data
     496----------------------------------------
     497
     498All date and time data LINTER storage in one type `DATE`_. LinPy by default
     499returned all data in ``datetime.datetime`` format, if need get data in
     500``datetime.date`` format, then you will use LINTER backend function
     501``set_date_emulation``. This function set mode conversion values ``datetime``
     502type to ``date`` type, if data contain values only for year, month and day.
     503This mode conversion values used in tests ``serializers``, ``model_forms``
     504from Django's test suite. This tests is necessary edit in the following way.
     505At the beggining of tests need to add strings::
     506   
     507    >>> from django.db import connection
     508    >>> connection.set_date_emulation(1)
     509
     510In this case tests will execute completely.
     511
     512.. _`DATE`: http://www.lintersql.com/en/documentation/pdf/sql.pdf
  • docs/ref/settings.txt

     
    152152Default: ``''`` (Empty string)
    153153
    154154The database backend to use. The built-in database backends are
    155 ``'postgresql_psycopg2'``, ``'postgresql'``, ``'mysql'``, ``'sqlite3'``, and
    156 ``'oracle'``.
     155``'postgresql_psycopg2'``, ``'postgresql'``, ``'mysql'``, ``'sqlite3'``,
     156``'oracle'`` and ``'linter'``.
    157157
    158158You can use a database backend that doesn't ship with Django by setting
    159159``DATABASE_ENGINE`` to a fully-qualified path (i.e.
  • docs/topics/install.txt

     
    6161
    6262If you plan to use Django's database API functionality, you'll need to
    6363make sure a database server is running. Django works with PostgreSQL_,
    64 MySQL_, Oracle_ and SQLite_ (although SQLite doesn't require a separate server
     64MySQL_, Oracle_, LINTER_ and SQLite_ (although SQLite doesn't require a separate server
    6565to be running).
    6666
    6767Additionally, you'll need to make sure your Python database bindings are
     
    8686  4.3.1 or higher. You will also want to read the database-specific notes for
    8787  the :ref:`Oracle backend <oracle-notes>`.
    8888
     89* If you're using LINTER, you'll need LinPy.dll. You will also want to read
     90  the database-specific notes for the :ref:`LINTER backend <ref-databases>`.
     91
    8992If you plan to use Django's ``manage.py syncdb`` command to
    9093automatically create database tables for your models, you'll need to
    9194ensure that Django has permission to create and alter tables in the
     
    108111.. _pysqlite: http://initd.org/pub/software/pysqlite/
    109112.. _cx_Oracle: http://cx-oracle.sourceforge.net/
    110113.. _Oracle: http://www.oracle.com/
     114.. _LINTER: http://www.lintersql.com/
    111115
    112116.. _removing-old-versions-of-django:
    113117
Back to Top