Index: contrib/sessions/middleware.py
===================================================================
--- contrib/sessions/middleware.py	(revision 5596)
+++ contrib/sessions/middleware.py	(working copy)
@@ -59,8 +59,11 @@
                 self._session_cache = {}
             else:
                 try:
+                    datenow = datetime.datetime.now()
+                    if hasattr(datenow, 'microsecond'):
+                        datenow = datenow.replace(microsecond=0)
                     s = Session.objects.get(session_key=self.session_key,
-                        expire_date__gt=datetime.datetime.now())
+                        expire_date__gt=datenow)
                     self._session_cache = s.get_decoded()
                 except (Session.DoesNotExist, SuspiciousOperation):
                     self._session_cache = {}
Index: db/backends/mssql/base.py
===================================================================
--- db/backends/mssql/base.py	(revision 0)
+++ db/backends/mssql/base.py	(revision 0)
@@ -0,0 +1,510 @@
+"""
+Alpha Multi-plataform MSSQL database backend for Django.
+
+Requires pymssql >= v0.8.0: http://pymssql.sourceforge.net/
+"""
+if __name__ == '__main__':
+    import sys
+    import os
+    
+    SETTINGS_MODULE = 'settings'
+    
+    project_dir = r'E:\Proyectos\Python\mysite'
+    sys.path.append(os.path.join(project_dir, '..'))
+    sys.path.append("..")
+    sys.path.pop()
+    os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
+
+import datetime
+from django.db.backends import util
+from django.core.exceptions import ImproperlyConfigured
+from django.utils.datastructures import SortedDict
+
+try:
+    import pymssql as Database
+except ImportError, e:
+    raise ImproperlyConfigured, "Error loading pymssql module: %s" % e
+
+try:
+    import mx
+except ImportError:
+    mx = None
+
+try:
+    # Only exists in Python 2.4+
+    from threading import local
+except ImportError:
+    # Import copy of _thread_local.py from Python 2.4
+    from django.utils._threading_local import local
+
+DatabaseError = Database.DatabaseError
+IntegrityError = Database.IntegrityError
+
+#Configure support options:
+allows_group_by_ordinal = True
+allows_unique_and_pk = True
+autoindexes_primary_keys = True
+needs_datetime_string_cast = True
+needs_upper_for_iops = False
+supports_constraints = True
+supports_tablespaces = False
+uses_case_insensitive_names = False
+
+def complain(*args, **kwargs):
+    raise ImproperlyConfigured, "You haven't set the DATABASE_ENGINE setting yet."
+
+def ignore(*args, **kwargs):
+    pass
+
+class DatabaseError(Exception):
+    pass
+
+class IntegrityError(DatabaseError):
+    pass
+
+class DatabaseWrapper(local):
+    def __init__(self, **kwargs):
+        self.connection = None
+        self.queries = []
+
+    def cursor(self):
+        from django.conf import settings
+        if self.connection is None:
+            if settings.DATABASE_NAME == '' or settings.DATABASE_USER == '':
+                raise ImproperlyConfigured, "You need to specify both DATABASE_NAME and DATABASE_USER in your Django settings file."
+            if not settings.DATABASE_HOST:
+                settings.DATABASE_HOST = "127.0.0.1"
+
+            if settings.DATABASE_PORT:
+                hostStr = '%s:%s' % ( settings.DATABASE_HOST ,settings.DATABASE_PORT)
+            else:
+                hostStr = settings.DATABASE_HOST
+
+            self.connection = Database.connect(host=hostStr,user=settings.DATABASE_USER,password=settings.DATABASE_PASSWORD,database=settings.DATABASE_NAME)
+        
+        self.connection.cursor().execute("SET DATEFORMAT ymd\nGO")
+        
+        cursor = self.connection.cursor()
+        if settings.DEBUG:
+            return util.CursorDebugWrapper(cursor, self)
+        return cursor
+
+    def _commit(self):
+        if self.connection is not None:
+            return self.connection.commit()
+
+    def _rollback(self):
+        if self.connection is not None:
+            return self.connection.rollback()
+
+    def close(self):
+        if self.connection is not None:
+            self.connection.close()
+            self.connection = None
+
+'''
+    Return the major version of the server. 7=Sql 7,8=Sql2000,9=Sql2005
+'''
+def version():
+    cur = DatabaseWrapper().cursor()
+    cur.execute("SELECT SERVERPROPERTY('ProductVersion')")
+    
+    return int(cur.fetchone()[0].split('.')[0])
+
+def quote_name(name):
+    if name.startswith('[') and name.endswith(']'):
+        return name # Quoting once is enough.
+    return '[%s]' % name
+
+dictfetchone = util.dictfetchone
+dictfetchmany = util.dictfetchmany
+dictfetchall  = util.dictfetchall
+
+def get_last_insert_id(cursor, table_name, pk_name):
+    cursor.execute("SELECT %s FROM %s WHERE %s = IDENT_CURRENT('%s')" % (pk_name, table_name, pk_name,table_name)) 
+    return cursor.fetchone()[0]
+
+def get_date_extract_sql(lookup_type, table_name):
+    # lookup_type is 'year', 'month', 'day'
+    return "DATEPART(%s, %s)" % (lookup_type, table_name)
+
+def get_date_trunc_sql(lookup_type, field_name):
+    # lookup_type is 'year', 'month', 'day'
+    if lookup_type=='year':
+        return "Convert(datetime, Convert(varchar, DATEPART(year, %s)) + '/01/01')" % field_name
+    if lookup_type=='month':
+        return "Convert(datetime, Convert(varchar, DATEPART(year, %s)) + '/' + Convert(varchar, DATEPART(month, %s)) + '/01')" % (field_name, field_name)
+    if lookup_type=='day':
+        return "Convert(datetime, Convert(varchar(12), %s))" % field_name
+
+def get_datetime_cast_sql():
+    return None
+
+def get_limit_offset_sql(limit, offset=None):
+    # Limits and offset are too complicated to be handled here.
+    # Look for a implementation similar to SqlServer backend
+    return ""
+
+def get_random_function_sql():
+    return "RAND()"
+
+def get_deferrable_sql():
+    # TODO: Workaround cicle paths...
+    # DEFERRABLE and INITALLY DEFFERRED are not apparently supported on constraints
+    # This cause SQL Server message 1750, severity 16, state 0, for example in the multiple joins path of comments.
+    # So, this left Sql Server as if have not relations :(
+    #return " ON DELETE CASCADE ON UPDATE CASCADE"
+    return "" 
+
+def get_fulltext_search_sql(field_name):
+    raise NotImplementedError
+
+def get_drop_foreignkey_sql():
+    return "DROP CONSTRAINT"
+
+def get_pk_default_value():
+    return "DEFAULT"
+
+def get_max_name_length():
+    return None
+
+def get_start_transaction_sql():
+    return "BEGIN;"
+
+def get_tablespace_sql(tablespace, inline=False):
+    return "ON %s" % quote_name(tablespace)
+
+def get_autoinc_sql(table):
+    return None
+
+def get_sql_flush(sql_styler, full_table_list, sequences): 
+    """Return a list of SQL statements required to remove all data from
+    all tables in the database (without actually removing the tables
+    themselves) and put the database in an empty 'initial' state
+    """
+    # Cannot use TRUNCATE on tables that are reference by a FOREIGN KEY
+    # So must use the much slower DELETE
+    sql_list = ['%s %s %s;' % \
+                (sql_styler.SQL_KEYWORD('DELETE'),
+                sql_styler.SQL_KEYWORD('FROM'),
+                sql_styler.SQL_FIELD(quote_name(table))
+                )  for table in full_table_list]
+    #The reset the counters on each table.
+    sql_list.extend(['%s %s %s %s %s %s %s;' % (
+        sql_styler.SQL_KEYWORD('DBCC'),
+        sql_styler.SQL_KEYWORD('CHECKIDENT'),
+        sql_styler.SQL_FIELD(quote_name(seq["table"])),
+        sql_styler.SQL_KEYWORD('RESEED'),
+        sql_styler.SQL_FIELD('1'),
+        sql_styler.SQL_KEYWORD('WITH'),
+        sql_styler.SQL_KEYWORD('NO_INFOMSGS'),
+        ) for seq in sequences])
+    
+    return sql_list 
+
+def get_sql_sequence_reset(style, model_list):
+    "Returns a list of the SQL statements to reset sequences for the given models."
+    # No sequence reset required
+    return []
+
+def get_trigger_name(table):
+    return '%s_TR' % table.upper()
+
+def get_query_set_class(DefaultQuerySet):
+    "Create a custom QuerySet class for SqlServer."
+
+    from django.db import backend, connection
+    from django.db.models.query import EmptyResultSet, GET_ITERATOR_CHUNK_SIZE, quote_only_if_word
+
+    class SqlServerQuerySet(DefaultQuerySet):
+
+        def iterator(self):
+            "Performs the SELECT database lookup of this QuerySet."
+
+            from django.db.models.query import get_cached_row
+
+            # self._select is a dictionary, and dictionaries' key order is
+            # undefined, so we convert it to a list of tuples.
+            extra_select = self._select.items()
+
+            full_query = None
+
+            try:
+                try:
+                    select, sql, params, full_query = self._get_sql_clause(get_full_query=True)
+                except TypeError:
+                    select, sql, params = self._get_sql_clause()
+            except EmptyResultSet:
+                raise StopIteration
+            if not full_query:
+                full_query = "SELECT %s%s\n%s" % \
+                             ((self._distinct and "DISTINCT " or ""),
+                              ', '.join(select), sql)
+
+            cursor = connection.cursor()
+            cursor.execute(full_query, params)
+
+            fill_cache = self._select_related
+            fields = self.model._meta.fields
+            index_end = len(fields)
+
+            # so here's the logic;
+            # 1. retrieve each row in turn
+            # 2. convert NCLOBs
+
+            while 1:
+                rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE)
+                if not rows:
+                    raise StopIteration
+                for row in rows:
+                    row = self.resolve_columns(row, fields)
+                    if fill_cache:
+                        obj, index_end = get_cached_row(klass=self.model, row=row,
+                                                        index_start=0, max_depth=self._max_related_depth)
+                    else:
+                        obj = self.model(*row[:index_end])
+                    for i, k in enumerate(extra_select):
+                        setattr(obj, k[0], row[index_end+i])
+                    yield obj
+
+
+        def _get_sql_clause(self, get_full_query=False):
+            from django.db.models.query import fill_table_cache, \
+                handle_legacy_orderlist, orderfield2column
+
+            opts = self.model._meta
+
+            # Construct the fundamental parts of the query: SELECT X FROM Y WHERE Z.
+            select = ["%s.%s" % (backend.quote_name(opts.db_table), backend.quote_name(f.column)) for f in opts.fields]
+            tables = [quote_only_if_word(t) for t in self._tables]
+            joins = SortedDict()
+            where = self._where[:]
+            params = self._params[:]
+
+            # Convert self._filters into SQL.
+            joins2, where2, params2 = self._filters.get_sql(opts)
+            joins.update(joins2)
+            where.extend(where2)
+            params.extend(params2)
+
+            # Add additional tables and WHERE clauses based on select_related.
+            if self._select_related:
+                fill_table_cache(opts, select, tables, where, opts.db_table, [opts.db_table])
+
+            # Add any additional SELECTs.
+            if self._select:
+                select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in self._select.items()])
+
+            # Start composing the body of the SQL statement.
+            sql = [" FROM", backend.quote_name(opts.db_table)]
+
+            # Compose the join dictionary into SQL describing the joins.
+            if joins:
+                sql.append(" ".join(["%s %s %s ON %s" % (join_type, table, alias, condition)
+                                for (alias, (table, join_type, condition)) in joins.items()]))
+
+            # Compose the tables clause into SQL.
+            if tables:
+                sql.append(", " + ", ".join(tables))
+
+            # Compose the where clause into SQL.
+            if where:
+                sql.append(where and "WHERE " + " AND ".join(where))
+            
+            #copy a version suitable for LIMIT
+            sql2=[]
+            [sql2.append(x) for x in sql]            
+            # ORDER BY clause
+            order_by = []
+            if self._order_by is not None:
+                ordering_to_use = self._order_by
+            else:
+                ordering_to_use = opts.ordering
+            for f in handle_legacy_orderlist(ordering_to_use):
+                if f == '?': # Special case.
+                    order_by.append(backend.get_random_function_sql())
+                else:
+                    if f.startswith('-'):
+                        col_name = f[1:]
+                        order = "DESC"
+                    else:
+                        col_name = f
+                        order = "ASC"
+                    if "." in col_name:
+                        table_prefix, col_name = col_name.split('.', 1)
+                        table_prefix = backend.quote_name(table_prefix) + '.'
+                    else:
+                        # Use the database table as a column prefix if it wasn't given,
+                        # and if the requested column isn't a custom SELECT.
+                        if "." not in col_name and col_name not in (self._select or ()):
+                            table_prefix = backend.quote_name(opts.db_table) + '.'
+                        else:
+                            table_prefix = ''
+                    order_by.append('%s%s %s' % (table_prefix, backend.quote_name(orderfield2column(col_name, opts)), order))
+            if order_by:
+                sql.append("ORDER BY " + ", ".join(order_by))
+
+            # Look for column name collisions in the select elements
+            # and fix them with an AS alias.  This allows us to do a
+            # SELECT * later in the paging query.
+            cols = [clause.split('.')[-1] for clause in select]
+            for index, col in enumerate(cols):
+                if cols.count(col) > 1:
+                    col = '%s%d' % (col.replace('[', '').replace(']',''), index)
+                    cols[index] = backend.quote_name(col)
+                    select[index] = '%s AS %s' % (select[index], backend.quote_name(col))
+
+            # LIMIT and OFFSET clauses
+            # To support limits and offsets, SqlServer requires some funky rewriting of an otherwise normal looking query.
+            select_clause = ",".join(select)
+            distinct = (self._distinct and "DISTINCT " or "")            
+            full_query = None
+            
+            if self._limit is None:
+                assert self._offset is None, "'offset' is not allowed without 'limit'"
+
+            if self._offset is not None:
+                offset = int(self._offset)
+            else:
+                offset = 0
+
+            if self._limit is not None:
+                limit = int(self._limit)
+            else:
+                limit = None
+            
+            limit_and_offset_clause = ''
+
+            if limit is not None:
+                limit_and_offset_clause = True
+            elif offset:
+                limit_and_offset_clause = True
+            
+            if limit_and_offset_clause:
+                #Django give:
+                # Offset : Start row
+                # Limit : How much aditional rows fetch
+                
+                # This must be transformed to Sql2005 to:
+                # Offset : First Row
+                # Limit : EndRow
+                StartRow = offset + 1
+                EndRow = StartRow + limit - 1
+                # and for Sql2000
+                # Offset : Top rows
+                # Limit: From where
+                limit = limit + offset
+                if offset==0:
+                    offset = limit
+                else:
+                    offset = offset + 1
+                #Must use a order. If not specified, use Id.
+                if len(order_by)==0:
+                    order_by.append('%s.%s ASC' %
+                        (backend.quote_name(opts.db_table),
+                        backend.quote_name(opts.fields[0].db_column or opts.fields[0].column)
+                        )
+                    )
+
+                order_by_clause = ", ".join(order_by)
+                order_by_clauseReverse = ""
+
+                #For Sql2005+ use native implementation...
+                if version()>8:
+                    fmt = \
+"""
+SELECT *
+FROM (
+    SELECT %(distinc)s TOP %(EndRow)s
+        %(fields)s, ROW_NUMBER()
+        OVER(
+            ORDER BY  %(orderby)s
+        ) AS row
+    %(sql)s ORDER BY %(orderby)s
+    ) AS x
+    WHERE x.row BETWEEN %(StartRow)s AND %(EndRow)s
+"""
+                else:    
+                    #Is necesary reverse all the second order by for the trick to work...
+                    order_by_clauseReverse= ", ".join(self.change_order_direction(order_by))
+                    
+                    fmt = \
+"""
+SELECT * FROM (
+  SELECT TOP %(offset)s * FROM (
+    SELECT TOP %(limit)s %(distinc)s%(fields)s
+        %(sql)s    
+    ORDER BY %(orderby)s
+  ) AS %(table)s
+  ORDER BY %(orderbyReverse)s) AS %(table)s
+ORDER BY %(orderby)s
+"""
+
+                full_query = fmt % {'distinc':distinct, 'fields':select_clause,
+                                        'sql':" ".join(sql2),'orderby':order_by_clause,
+                                        'orderbyReverse':order_by_clauseReverse,
+                                        'table':backend.quote_name(opts.db_table),
+                                        'offset':offset,'limit':limit,
+                                        'StartRow':StartRow,'EndRow':EndRow}
+            
+            print full_query
+            if get_full_query:
+                return select, " ".join(sql), params, full_query
+            else:
+                return select, " ".join(sql), params
+
+
+        def change_order_direction(self,order_by):
+            newOrder=[]
+            
+            for order in order_by:
+                if order.find(' ASC'):
+                    newOrder.append(order.replace(' ASC',' DESC'))
+                else:
+                    newOrder.append(order.replace(' DESC',' ASC'))
+            
+            return newOrder
+
+        def resolve_columns(self, row, fields=()):
+            from django.db.models.fields import DateField, DateTimeField, \
+                TimeField, BooleanField, NullBooleanField, DecimalField, Field
+            values = []
+            for value, field in map(None, row, fields):
+                # Convert 1 or 0 to True or False
+                if value in (1, 0) and isinstance(field, (BooleanField, NullBooleanField)):
+                    value = bool(value)
+                # Convert floats to decimals
+                elif value is not None and isinstance(field, DecimalField):
+                    value = util.typecast_decimal(field.format_number(value))
+                values.append(value)
+            return values
+
+    return SqlServerQuerySet
+
+OPERATOR_MAPPING = {
+    'exact': '= %s',
+    'iexact': 'LIKE %s',
+    'contains': 'LIKE %s',
+    'icontains': 'LIKE %s',
+    'gt': '> %s',
+    'gte': '>= %s',
+    'lt': '< %s',
+    'lte': '<= %s',
+    'startswith': 'LIKE %s',
+    'endswith': 'LIKE %s',
+    'istartswith': 'LIKE %s',
+    'iendswith': 'LIKE %s',
+}
+
+if __name__ == '__main__': 
+    from mysite.polls.models import Poll, Choice
+    from datetime import datetime
+    
+    #Poll.objects.all().delete()
+    #i =0
+    #for i in range(i,150):
+    #    p = Poll(question="%s" % i, pub_date=datetime.now())
+    #    p.save()
+
+    for poll in Poll.objects.all()[:10]:
+        print poll
\ No newline at end of file
Index: db/backends/mssql/client.py
===================================================================
--- db/backends/mssql/client.py	(revision 0)
+++ db/backends/mssql/client.py	(revision 0)
@@ -0,0 +1,37 @@
+from django.conf import settings
+import os
+import sys
+
+def runshell():
+    if os.name=='nt':
+        args = ['']
+        db = settings.DATABASE_OPTIONS.get('db', settings.DATABASE_NAME)
+        user = settings.DATABASE_OPTIONS.get('user', settings.DATABASE_USER)
+        passwd = settings.DATABASE_OPTIONS.get('passwd', settings.DATABASE_PASSWORD)
+        host = settings.DATABASE_OPTIONS.get('host', settings.DATABASE_HOST)
+        port = settings.DATABASE_OPTIONS.get('port', settings.DATABASE_PORT)
+        defaults_file = settings.DATABASE_OPTIONS.get('read_default_file')
+        # Seems to be no good way to set sql_mode with CLI
+        
+        if defaults_file:
+            args += ["-i %s" % defaults_file]
+        if user:
+            args += ["-U %s" % user]
+        if passwd:
+            args += ["-P %s" % passwd]
+        if host:
+            args += ["-E %s" % host]
+        if db:
+            args += ["-d %s" % db]
+    
+        cmd = "osql %s" % ' '.join(args)
+    
+        rv = os.system(cmd)
+        if (rv):
+           print "Error al ejecutar %s " % rv
+           sys.exit(rv)
+    else:
+        raise NotImplementedError
+
+    
+    
Index: db/backends/mssql/__init__.py
===================================================================
Index: db/backends/mssql/introspection.py
===================================================================
--- db/backends/mssql/introspection.py	(revision 0)
+++ db/backends/mssql/introspection.py	(revision 0)
@@ -0,0 +1,137 @@
+def get_table_list(cursor):
+    "Returns a list of table names in the current database."
+    cursor.execute("SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'")
+    return [row[2] for row in cursor.fetchall()]
+
+def _is_auto_field(cursor, table_name, column_name):
+    cursor.execute("SELECT COLUMNPROPERTY( OBJECT_ID('%s'),'%s','IsIdentity')" % (table_name, column_name))
+    return cursor.fetchall()[0][0]
+
+def get_table_description(cursor, table_name, identity_check=True):
+    """Returns a description of the table, with the DB-API cursor.description interface.
+
+    The 'auto_check' parameter has been added to the function argspec.
+    If set to True, the function will check each of the table's fields for the
+    IDENTITY property (the IDENTITY property is the MSSQL equivalent to an AutoField).
+
+    When a field is found with an IDENTITY property, it is given a custom field number
+    of -777, which maps to the 'AutoField' value in the DATA_TYPES_REVERSE dict.
+    """    
+    cursor.execute("SELECT TOP 1 * FROM %s" % table_name)
+    cursor.nextset()
+    items = []
+    if identity_check:
+        for data in cursor.description:
+            if _is_auto_field(cursor, table_name, data[0]):
+                data = list(data)
+                data[1] = -777
+            items.append(list(data))
+    else:
+        items = cursor.description
+    return items
+
+def _name_to_index(cursor, table_name):
+    """
+    Returns a dictionary of {field_name: field_index} for the given table.
+    Indexes are 0-based.
+    """
+    return dict([(d[0], i) for i, d in enumerate(get_table_description(cursor, table_name, identity_check=False))])
+
+def get_relations(cursor, table_name):
+    """
+    Returns a dictionary of {field_index: (field_index_other_table, other_table)}
+    representing all relationships to the given table. Indexes are 0-based.    
+    """
+    table_index = _name_to_index(cursor, table_name)
+    sql = """SELECT e.COLUMN_NAME AS column_name,
+                    c.TABLE_NAME AS referenced_table_name,
+                    d.COLUMN_NAME AS referenced_column_name
+                    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS a
+                        INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS b
+                              ON a.CONSTRAINT_NAME = b.CONSTRAINT_NAME
+                        INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE AS c
+                              ON b.UNIQUE_CONSTRAINT_NAME = c.CONSTRAINT_NAME
+                        INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS d
+                              ON c.CONSTRAINT_NAME = d.CONSTRAINT_NAME
+                        INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS e
+                              ON a.CONSTRAINT_NAME = e.CONSTRAINT_NAME
+                    WHERE a.TABLE_NAME = ? AND
+                          a.CONSTRAINT_TYPE = 'FOREIGN KEY'"""
+    cursor = Cursor(cursor.db.connection)
+    cursor.execute(sql, (table_name,))
+    return dict([(table_index[item[0]], (_name_to_index(cursor, item[1])[item[2]], item[1]))
+                  for item in cursor.fetchall()])
+    
+def get_indexes(cursor, table_name):
+    """
+    Returns a dictionary of fieldname -> infodict for the given table,
+    where each infodict is in the format:
+        {'primary_key': boolean representing whether it's the primary key,
+         'unique': boolean representing whether it's a unique index}
+    """
+    sql = """SELECT b.COLUMN_NAME, a.CONSTRAINT_TYPE
+               FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS a INNER JOIN
+                    INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS b
+                    ON a.CONSTRAINT_NAME = b.CONSTRAINT_NAME AND
+                       a.TABLE_NAME = b.TABLE_NAME
+               WHERE a.TABLE_NAME = ? AND
+                     (CONSTRAINT_TYPE = 'PRIMARY KEY' OR
+                      CONSTRAINT_TYPE = 'UNIQUE')"""
+    field_names = [item[0] for item in get_table_description(cursor, table_name, identity_check=False)]
+    cursor = Cursor(cursor.db.connection)
+    cursor.execute(sql, (table_name,))
+    indexes = {}
+    results = {}
+    data = cursor.fetchall()
+    if data:
+        results.update(data)
+    for field in field_names:
+        val = results.get(field, None)
+        indexes[field] = dict(primary_key=(val=='PRIMARY KEY'), unique=(val=='UNIQUE'))
+    return indexes
+
+# A reference for the values below:
+# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/mdcstdatatypeenum.asp
+DATA_TYPES_REVERSE = {
+# 8192 : Array ,
+# 128 : Binary ,
+# 9 : IDispatch ,
+# 12 : Variant ,
+# 13 : IUnknown ,
+# 21  : UnsignedBigInt,
+# 132 : UserDefined ,
+# 0   : Empty ,
+# 136 : Chapter ,
+# 138 : PropVariant ,
+# 204 : VarBinary ,
+# 205 : LongVarBinary ,
+-777: 'AutoField',                  # Custom number used to identify AutoFields
+2   : 'SmallIntegerField',          # SmallInt
+3   : 'IntegerField',               # Integer
+4   : 'FloatField',                 # Single
+5   : 'FloatField',                 # Decimal
+6   : 'FloatField',                 # Currency
+7   : 'DateField',                  # Date
+8   : 'CharField',                  # BSTR
+10  : 'IntegerField',               # Error
+11  : 'BooleanField',               # Boolean
+14  : 'FloatField',                 # Decimal
+16  : 'SmallIntegerField',          # TinyInt
+17  : 'PositiveSmallIntegerField',  # UnsignedTinyInt
+18  : 'PositiveSmallIntegerField',  # UnsignedSmallInt
+19  : 'PositiveIntegerField',       # UnsignedInt
+20  : 'IntegerField',               # BigInt
+64  : 'DateTimeField',              # FileTime
+72  : 'CharField',                  # GUID
+129 : 'CharField',                  # Char
+130 : 'CharField',                  # WChar
+131 : 'FloatField',                 # Numeric
+133 : 'DateField',                  # DBDate
+134 : 'TimeField',                  # DBTime
+135 : 'DateTimeField',              # DBTimeStamp
+139 : 'FloatField',                 # VarNumeric
+200 : 'CharField',                  # VarChar
+201 : 'TextField',                  # LongVarChar
+202 : 'CharField',                  # VarWChar
+203 : 'TextField',                  # LongVarWChar
+}
\ No newline at end of file
Index: db/backends/mssql/creation.py
===================================================================
--- db/backends/mssql/creation.py	(revision 0)
+++ db/backends/mssql/creation.py	(revision 0)
@@ -0,0 +1,27 @@
+DATA_TYPES = {
+    'AutoField':         'int IDENTITY (1, 1)',
+    'BooleanField':      'bit',
+    'CharField':         'varchar(%(maxlength)s)',
+    'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
+    'DateField':         'datetime',
+    'DateTimeField':     'datetime',
+    'DecimalField':      'numeric(%(max_digits)s, %(decimal_places)s)',
+    'FileField':         'varchar(254)',
+    'FilePathField':     'varchar(254)',
+    'FloatField':        'double precision',
+    'ImageField':        'varchar(254)',
+    'IntegerField':      'int',
+    'IPAddressField':    'char(15)',
+    'ManyToManyField':   None,
+    'NullBooleanField':  'bit',
+    'OneToOneField':     'int',
+    'PhoneNumberField':  'varchar(20)',
+    #The check must be unique in for the database. Put random so the regresion test not complain about duplicate names
+    'PositiveIntegerField': 'int CONSTRAINT [CK_int_pos_%(creation_counter)s_%(column)s] CHECK ([%(column)s] > 0)',    
+    'PositiveSmallIntegerField': 'smallint CONSTRAINT [CK_smallint_pos_%(creation_counter)s_%(column)s] CHECK ([%(column)s] > 0)',
+    'SlugField':         'varchar(%(maxlength)s)',
+    'SmallIntegerField': 'smallint',
+    'TextField':         'text',
+    'TimeField':         'datetime',
+    'USStateField':      'varchar(2)',
+}
Index: db/backends/mssql/__init__.py
===================================================================
Index: db/backends/mssql/base.py
===================================================================
--- db/backends/mssql/base.py	(revision 0)
+++ db/backends/mssql/base.py	(revision 0)
@@ -0,0 +1,510 @@
+"""
+Alpha Multi-plataform MSSQL database backend for Django.
+
+Requires pymssql >= v0.8.0: http://pymssql.sourceforge.net/
+"""
+if __name__ == '__main__':
+    import sys
+    import os
+    
+    SETTINGS_MODULE = 'settings'
+    
+    project_dir = r'E:\Proyectos\Python\mysite'
+    sys.path.append(os.path.join(project_dir, '..'))
+    sys.path.append("..")
+    sys.path.pop()
+    os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
+
+import datetime
+from django.db.backends import util
+from django.core.exceptions import ImproperlyConfigured
+from django.utils.datastructures import SortedDict
+
+try:
+    import pymssql as Database
+except ImportError, e:
+    raise ImproperlyConfigured, "Error loading pymssql module: %s" % e
+
+try:
+    import mx
+except ImportError:
+    mx = None
+
+try:
+    # Only exists in Python 2.4+
+    from threading import local
+except ImportError:
+    # Import copy of _thread_local.py from Python 2.4
+    from django.utils._threading_local import local
+
+DatabaseError = Database.DatabaseError
+IntegrityError = Database.IntegrityError
+
+#Configure support options:
+allows_group_by_ordinal = True
+allows_unique_and_pk = True
+autoindexes_primary_keys = True
+needs_datetime_string_cast = True
+needs_upper_for_iops = False
+supports_constraints = True
+supports_tablespaces = False
+uses_case_insensitive_names = False
+
+def complain(*args, **kwargs):
+    raise ImproperlyConfigured, "You haven't set the DATABASE_ENGINE setting yet."
+
+def ignore(*args, **kwargs):
+    pass
+
+class DatabaseError(Exception):
+    pass
+
+class IntegrityError(DatabaseError):
+    pass
+
+class DatabaseWrapper(local):
+    def __init__(self, **kwargs):
+        self.connection = None
+        self.queries = []
+
+    def cursor(self):
+        from django.conf import settings
+        if self.connection is None:
+            if settings.DATABASE_NAME == '' or settings.DATABASE_USER == '':
+                raise ImproperlyConfigured, "You need to specify both DATABASE_NAME and DATABASE_USER in your Django settings file."
+            if not settings.DATABASE_HOST:
+                settings.DATABASE_HOST = "127.0.0.1"
+
+            if settings.DATABASE_PORT:
+                hostStr = '%s:%s' % ( settings.DATABASE_HOST ,settings.DATABASE_PORT)
+            else:
+                hostStr = settings.DATABASE_HOST
+
+            self.connection = Database.connect(host=hostStr,user=settings.DATABASE_USER,password=settings.DATABASE_PASSWORD,database=settings.DATABASE_NAME)
+        
+        self.connection.cursor().execute("SET DATEFORMAT ymd\nGO")
+        
+        cursor = self.connection.cursor()
+        if settings.DEBUG:
+            return util.CursorDebugWrapper(cursor, self)
+        return cursor
+
+    def _commit(self):
+        if self.connection is not None:
+            return self.connection.commit()
+
+    def _rollback(self):
+        if self.connection is not None:
+            return self.connection.rollback()
+
+    def close(self):
+        if self.connection is not None:
+            self.connection.close()
+            self.connection = None
+
+'''
+    Return the major version of the server. 7=Sql 7,8=Sql2000,9=Sql2005
+'''
+def version():
+    cur = DatabaseWrapper().cursor()
+    cur.execute("SELECT SERVERPROPERTY('ProductVersion')")
+    
+    return int(cur.fetchone()[0].split('.')[0])
+
+def quote_name(name):
+    if name.startswith('[') and name.endswith(']'):
+        return name # Quoting once is enough.
+    return '[%s]' % name
+
+dictfetchone = util.dictfetchone
+dictfetchmany = util.dictfetchmany
+dictfetchall  = util.dictfetchall
+
+def get_last_insert_id(cursor, table_name, pk_name):
+    cursor.execute("SELECT %s FROM %s WHERE %s = IDENT_CURRENT('%s')" % (pk_name, table_name, pk_name,table_name)) 
+    return cursor.fetchone()[0]
+
+def get_date_extract_sql(lookup_type, table_name):
+    # lookup_type is 'year', 'month', 'day'
+    return "DATEPART(%s, %s)" % (lookup_type, table_name)
+
+def get_date_trunc_sql(lookup_type, field_name):
+    # lookup_type is 'year', 'month', 'day'
+    if lookup_type=='year':
+        return "Convert(datetime, Convert(varchar, DATEPART(year, %s)) + '/01/01')" % field_name
+    if lookup_type=='month':
+        return "Convert(datetime, Convert(varchar, DATEPART(year, %s)) + '/' + Convert(varchar, DATEPART(month, %s)) + '/01')" % (field_name, field_name)
+    if lookup_type=='day':
+        return "Convert(datetime, Convert(varchar(12), %s))" % field_name
+
+def get_datetime_cast_sql():
+    return None
+
+def get_limit_offset_sql(limit, offset=None):
+    # Limits and offset are too complicated to be handled here.
+    # Look for a implementation similar to SqlServer backend
+    return ""
+
+def get_random_function_sql():
+    return "RAND()"
+
+def get_deferrable_sql():
+    # TODO: Workaround cicle paths...
+    # DEFERRABLE and INITALLY DEFFERRED are not apparently supported on constraints
+    # This cause SQL Server message 1750, severity 16, state 0, for example in the multiple joins path of comments.
+    # So, this left Sql Server as if have not relations :(
+    #return " ON DELETE CASCADE ON UPDATE CASCADE"
+    return "" 
+
+def get_fulltext_search_sql(field_name):
+    raise NotImplementedError
+
+def get_drop_foreignkey_sql():
+    return "DROP CONSTRAINT"
+
+def get_pk_default_value():
+    return "DEFAULT"
+
+def get_max_name_length():
+    return None
+
+def get_start_transaction_sql():
+    return "BEGIN;"
+
+def get_tablespace_sql(tablespace, inline=False):
+    return "ON %s" % quote_name(tablespace)
+
+def get_autoinc_sql(table):
+    return None
+
+def get_sql_flush(sql_styler, full_table_list, sequences): 
+    """Return a list of SQL statements required to remove all data from
+    all tables in the database (without actually removing the tables
+    themselves) and put the database in an empty 'initial' state
+    """
+    # Cannot use TRUNCATE on tables that are reference by a FOREIGN KEY
+    # So must use the much slower DELETE
+    sql_list = ['%s %s %s;' % \
+                (sql_styler.SQL_KEYWORD('DELETE'),
+                sql_styler.SQL_KEYWORD('FROM'),
+                sql_styler.SQL_FIELD(quote_name(table))
+                )  for table in full_table_list]
+    #The reset the counters on each table.
+    sql_list.extend(['%s %s %s %s %s %s %s;' % (
+        sql_styler.SQL_KEYWORD('DBCC'),
+        sql_styler.SQL_KEYWORD('CHECKIDENT'),
+        sql_styler.SQL_FIELD(quote_name(seq["table"])),
+        sql_styler.SQL_KEYWORD('RESEED'),
+        sql_styler.SQL_FIELD('1'),
+        sql_styler.SQL_KEYWORD('WITH'),
+        sql_styler.SQL_KEYWORD('NO_INFOMSGS'),
+        ) for seq in sequences])
+    
+    return sql_list 
+
+def get_sql_sequence_reset(style, model_list):
+    "Returns a list of the SQL statements to reset sequences for the given models."
+    # No sequence reset required
+    return []
+
+def get_trigger_name(table):
+    return '%s_TR' % table.upper()
+
+def get_query_set_class(DefaultQuerySet):
+    "Create a custom QuerySet class for SqlServer."
+
+    from django.db import backend, connection
+    from django.db.models.query import EmptyResultSet, GET_ITERATOR_CHUNK_SIZE, quote_only_if_word
+
+    class SqlServerQuerySet(DefaultQuerySet):
+
+        def iterator(self):
+            "Performs the SELECT database lookup of this QuerySet."
+
+            from django.db.models.query import get_cached_row
+
+            # self._select is a dictionary, and dictionaries' key order is
+            # undefined, so we convert it to a list of tuples.
+            extra_select = self._select.items()
+
+            full_query = None
+
+            try:
+                try:
+                    select, sql, params, full_query = self._get_sql_clause(get_full_query=True)
+                except TypeError:
+                    select, sql, params = self._get_sql_clause()
+            except EmptyResultSet:
+                raise StopIteration
+            if not full_query:
+                full_query = "SELECT %s%s\n%s" % \
+                             ((self._distinct and "DISTINCT " or ""),
+                              ', '.join(select), sql)
+
+            cursor = connection.cursor()
+            cursor.execute(full_query, params)
+
+            fill_cache = self._select_related
+            fields = self.model._meta.fields
+            index_end = len(fields)
+
+            # so here's the logic;
+            # 1. retrieve each row in turn
+            # 2. convert NCLOBs
+
+            while 1:
+                rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE)
+                if not rows:
+                    raise StopIteration
+                for row in rows:
+                    row = self.resolve_columns(row, fields)
+                    if fill_cache:
+                        obj, index_end = get_cached_row(klass=self.model, row=row,
+                                                        index_start=0, max_depth=self._max_related_depth)
+                    else:
+                        obj = self.model(*row[:index_end])
+                    for i, k in enumerate(extra_select):
+                        setattr(obj, k[0], row[index_end+i])
+                    yield obj
+
+
+        def _get_sql_clause(self, get_full_query=False):
+            from django.db.models.query import fill_table_cache, \
+                handle_legacy_orderlist, orderfield2column
+
+            opts = self.model._meta
+
+            # Construct the fundamental parts of the query: SELECT X FROM Y WHERE Z.
+            select = ["%s.%s" % (backend.quote_name(opts.db_table), backend.quote_name(f.column)) for f in opts.fields]
+            tables = [quote_only_if_word(t) for t in self._tables]
+            joins = SortedDict()
+            where = self._where[:]
+            params = self._params[:]
+
+            # Convert self._filters into SQL.
+            joins2, where2, params2 = self._filters.get_sql(opts)
+            joins.update(joins2)
+            where.extend(where2)
+            params.extend(params2)
+
+            # Add additional tables and WHERE clauses based on select_related.
+            if self._select_related:
+                fill_table_cache(opts, select, tables, where, opts.db_table, [opts.db_table])
+
+            # Add any additional SELECTs.
+            if self._select:
+                select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in self._select.items()])
+
+            # Start composing the body of the SQL statement.
+            sql = [" FROM", backend.quote_name(opts.db_table)]
+
+            # Compose the join dictionary into SQL describing the joins.
+            if joins:
+                sql.append(" ".join(["%s %s %s ON %s" % (join_type, table, alias, condition)
+                                for (alias, (table, join_type, condition)) in joins.items()]))
+
+            # Compose the tables clause into SQL.
+            if tables:
+                sql.append(", " + ", ".join(tables))
+
+            # Compose the where clause into SQL.
+            if where:
+                sql.append(where and "WHERE " + " AND ".join(where))
+            
+            #copy a version suitable for LIMIT
+            sql2=[]
+            [sql2.append(x) for x in sql]            
+            # ORDER BY clause
+            order_by = []
+            if self._order_by is not None:
+                ordering_to_use = self._order_by
+            else:
+                ordering_to_use = opts.ordering
+            for f in handle_legacy_orderlist(ordering_to_use):
+                if f == '?': # Special case.
+                    order_by.append(backend.get_random_function_sql())
+                else:
+                    if f.startswith('-'):
+                        col_name = f[1:]
+                        order = "DESC"
+                    else:
+                        col_name = f
+                        order = "ASC"
+                    if "." in col_name:
+                        table_prefix, col_name = col_name.split('.', 1)
+                        table_prefix = backend.quote_name(table_prefix) + '.'
+                    else:
+                        # Use the database table as a column prefix if it wasn't given,
+                        # and if the requested column isn't a custom SELECT.
+                        if "." not in col_name and col_name not in (self._select or ()):
+                            table_prefix = backend.quote_name(opts.db_table) + '.'
+                        else:
+                            table_prefix = ''
+                    order_by.append('%s%s %s' % (table_prefix, backend.quote_name(orderfield2column(col_name, opts)), order))
+            if order_by:
+                sql.append("ORDER BY " + ", ".join(order_by))
+
+            # Look for column name collisions in the select elements
+            # and fix them with an AS alias.  This allows us to do a
+            # SELECT * later in the paging query.
+            cols = [clause.split('.')[-1] for clause in select]
+            for index, col in enumerate(cols):
+                if cols.count(col) > 1:
+                    col = '%s%d' % (col.replace('[', '').replace(']',''), index)
+                    cols[index] = backend.quote_name(col)
+                    select[index] = '%s AS %s' % (select[index], backend.quote_name(col))
+
+            # LIMIT and OFFSET clauses
+            # To support limits and offsets, SqlServer requires some funky rewriting of an otherwise normal looking query.
+            select_clause = ",".join(select)
+            distinct = (self._distinct and "DISTINCT " or "")            
+            full_query = None
+            
+            if self._limit is None:
+                assert self._offset is None, "'offset' is not allowed without 'limit'"
+
+            if self._offset is not None:
+                offset = int(self._offset)
+            else:
+                offset = 0
+
+            if self._limit is not None:
+                limit = int(self._limit)
+            else:
+                limit = None
+            
+            limit_and_offset_clause = ''
+
+            if limit is not None:
+                limit_and_offset_clause = True
+            elif offset:
+                limit_and_offset_clause = True
+            
+            if limit_and_offset_clause:
+                #Django give:
+                # Offset : Start row
+                # Limit : How much aditional rows fetch
+                
+                # This must be transformed to Sql2005 to:
+                # Offset : First Row
+                # Limit : EndRow
+                StartRow = offset + 1
+                EndRow = StartRow + limit - 1
+                # and for Sql2000
+                # Offset : Top rows
+                # Limit: From where
+                limit = limit + offset
+                if offset==0:
+                    offset = limit
+                else:
+                    offset = offset + 1
+                #Must use a order. If not specified, use Id.
+                if len(order_by)==0:
+                    order_by.append('%s.%s ASC' %
+                        (backend.quote_name(opts.db_table),
+                        backend.quote_name(opts.fields[0].db_column or opts.fields[0].column)
+                        )
+                    )
+
+                order_by_clause = ", ".join(order_by)
+                order_by_clauseReverse = ""
+
+                #For Sql2005+ use native implementation...
+                if version()>8:
+                    fmt = \
+"""
+SELECT *
+FROM (
+    SELECT %(distinc)s TOP %(EndRow)s
+        %(fields)s, ROW_NUMBER()
+        OVER(
+            ORDER BY  %(orderby)s
+        ) AS row
+    %(sql)s ORDER BY %(orderby)s
+    ) AS x
+    WHERE x.row BETWEEN %(StartRow)s AND %(EndRow)s
+"""
+                else:    
+                    #Is necesary reverse all the second order by for the trick to work...
+                    order_by_clauseReverse= ", ".join(self.change_order_direction(order_by))
+                    
+                    fmt = \
+"""
+SELECT * FROM (
+  SELECT TOP %(offset)s * FROM (
+    SELECT TOP %(limit)s %(distinc)s%(fields)s
+        %(sql)s    
+    ORDER BY %(orderby)s
+  ) AS %(table)s
+  ORDER BY %(orderbyReverse)s) AS %(table)s
+ORDER BY %(orderby)s
+"""
+
+                full_query = fmt % {'distinc':distinct, 'fields':select_clause,
+                                        'sql':" ".join(sql2),'orderby':order_by_clause,
+                                        'orderbyReverse':order_by_clauseReverse,
+                                        'table':backend.quote_name(opts.db_table),
+                                        'offset':offset,'limit':limit,
+                                        'StartRow':StartRow,'EndRow':EndRow}
+            
+            print full_query
+            if get_full_query:
+                return select, " ".join(sql), params, full_query
+            else:
+                return select, " ".join(sql), params
+
+
+        def change_order_direction(self,order_by):
+            newOrder=[]
+            
+            for order in order_by:
+                if order.find(' ASC'):
+                    newOrder.append(order.replace(' ASC',' DESC'))
+                else:
+                    newOrder.append(order.replace(' DESC',' ASC'))
+            
+            return newOrder
+
+        def resolve_columns(self, row, fields=()):
+            from django.db.models.fields import DateField, DateTimeField, \
+                TimeField, BooleanField, NullBooleanField, DecimalField, Field
+            values = []
+            for value, field in map(None, row, fields):
+                # Convert 1 or 0 to True or False
+                if value in (1, 0) and isinstance(field, (BooleanField, NullBooleanField)):
+                    value = bool(value)
+                # Convert floats to decimals
+                elif value is not None and isinstance(field, DecimalField):
+                    value = util.typecast_decimal(field.format_number(value))
+                values.append(value)
+            return values
+
+    return SqlServerQuerySet
+
+OPERATOR_MAPPING = {
+    'exact': '= %s',
+    'iexact': 'LIKE %s',
+    'contains': 'LIKE %s',
+    'icontains': 'LIKE %s',
+    'gt': '> %s',
+    'gte': '>= %s',
+    'lt': '< %s',
+    'lte': '<= %s',
+    'startswith': 'LIKE %s',
+    'endswith': 'LIKE %s',
+    'istartswith': 'LIKE %s',
+    'iendswith': 'LIKE %s',
+}
+
+if __name__ == '__main__': 
+    from mysite.polls.models import Poll, Choice
+    from datetime import datetime
+    
+    #Poll.objects.all().delete()
+    #i =0
+    #for i in range(i,150):
+    #    p = Poll(question="%s" % i, pub_date=datetime.now())
+    #    p.save()
+
+    for poll in Poll.objects.all()[:10]:
+        print poll
\ No newline at end of file
Index: db/backends/mssql/client.py
===================================================================
--- db/backends/mssql/client.py	(revision 0)
+++ db/backends/mssql/client.py	(revision 0)
@@ -0,0 +1,37 @@
+from django.conf import settings
+import os
+import sys
+
+def runshell():
+    if os.name=='nt':
+        args = ['']
+        db = settings.DATABASE_OPTIONS.get('db', settings.DATABASE_NAME)
+        user = settings.DATABASE_OPTIONS.get('user', settings.DATABASE_USER)
+        passwd = settings.DATABASE_OPTIONS.get('passwd', settings.DATABASE_PASSWORD)
+        host = settings.DATABASE_OPTIONS.get('host', settings.DATABASE_HOST)
+        port = settings.DATABASE_OPTIONS.get('port', settings.DATABASE_PORT)
+        defaults_file = settings.DATABASE_OPTIONS.get('read_default_file')
+        # Seems to be no good way to set sql_mode with CLI
+        
+        if defaults_file:
+            args += ["-i %s" % defaults_file]
+        if user:
+            args += ["-U %s" % user]
+        if passwd:
+            args += ["-P %s" % passwd]
+        if host:
+            args += ["-E %s" % host]
+        if db:
+            args += ["-d %s" % db]
+    
+        cmd = "osql %s" % ' '.join(args)
+    
+        rv = os.system(cmd)
+        if (rv):
+           print "Error al ejecutar %s " % rv
+           sys.exit(rv)
+    else:
+        raise NotImplementedError
+
+    
+    
Index: db/backends/mssql/creation.py
===================================================================
--- db/backends/mssql/creation.py	(revision 0)
+++ db/backends/mssql/creation.py	(revision 0)
@@ -0,0 +1,27 @@
+DATA_TYPES = {
+    'AutoField':         'int IDENTITY (1, 1)',
+    'BooleanField':      'bit',
+    'CharField':         'varchar(%(maxlength)s)',
+    'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
+    'DateField':         'datetime',
+    'DateTimeField':     'datetime',
+    'DecimalField':      'numeric(%(max_digits)s, %(decimal_places)s)',
+    'FileField':         'varchar(254)',
+    'FilePathField':     'varchar(254)',
+    'FloatField':        'double precision',
+    'ImageField':        'varchar(254)',
+    'IntegerField':      'int',
+    'IPAddressField':    'char(15)',
+    'ManyToManyField':   None,
+    'NullBooleanField':  'bit',
+    'OneToOneField':     'int',
+    'PhoneNumberField':  'varchar(20)',
+    #The check must be unique in for the database. Put random so the regresion test not complain about duplicate names
+    'PositiveIntegerField': 'int CONSTRAINT [CK_int_pos_%(creation_counter)s_%(column)s] CHECK ([%(column)s] > 0)',    
+    'PositiveSmallIntegerField': 'smallint CONSTRAINT [CK_smallint_pos_%(creation_counter)s_%(column)s] CHECK ([%(column)s] > 0)',
+    'SlugField':         'varchar(%(maxlength)s)',
+    'SmallIntegerField': 'smallint',
+    'TextField':         'text',
+    'TimeField':         'datetime',
+    'USStateField':      'varchar(2)',
+}
Index: db/backends/mssql/introspection.py
===================================================================
--- db/backends/mssql/introspection.py	(revision 0)
+++ db/backends/mssql/introspection.py	(revision 0)
@@ -0,0 +1,137 @@
+def get_table_list(cursor):
+    "Returns a list of table names in the current database."
+    cursor.execute("SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'")
+    return [row[2] for row in cursor.fetchall()]
+
+def _is_auto_field(cursor, table_name, column_name):
+    cursor.execute("SELECT COLUMNPROPERTY( OBJECT_ID('%s'),'%s','IsIdentity')" % (table_name, column_name))
+    return cursor.fetchall()[0][0]
+
+def get_table_description(cursor, table_name, identity_check=True):
+    """Returns a description of the table, with the DB-API cursor.description interface.
+
+    The 'auto_check' parameter has been added to the function argspec.
+    If set to True, the function will check each of the table's fields for the
+    IDENTITY property (the IDENTITY property is the MSSQL equivalent to an AutoField).
+
+    When a field is found with an IDENTITY property, it is given a custom field number
+    of -777, which maps to the 'AutoField' value in the DATA_TYPES_REVERSE dict.
+    """    
+    cursor.execute("SELECT TOP 1 * FROM %s" % table_name)
+    cursor.nextset()
+    items = []
+    if identity_check:
+        for data in cursor.description:
+            if _is_auto_field(cursor, table_name, data[0]):
+                data = list(data)
+                data[1] = -777
+            items.append(list(data))
+    else:
+        items = cursor.description
+    return items
+
+def _name_to_index(cursor, table_name):
+    """
+    Returns a dictionary of {field_name: field_index} for the given table.
+    Indexes are 0-based.
+    """
+    return dict([(d[0], i) for i, d in enumerate(get_table_description(cursor, table_name, identity_check=False))])
+
+def get_relations(cursor, table_name):
+    """
+    Returns a dictionary of {field_index: (field_index_other_table, other_table)}
+    representing all relationships to the given table. Indexes are 0-based.    
+    """
+    table_index = _name_to_index(cursor, table_name)
+    sql = """SELECT e.COLUMN_NAME AS column_name,
+                    c.TABLE_NAME AS referenced_table_name,
+                    d.COLUMN_NAME AS referenced_column_name
+                    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS a
+                        INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS b
+                              ON a.CONSTRAINT_NAME = b.CONSTRAINT_NAME
+                        INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE AS c
+                              ON b.UNIQUE_CONSTRAINT_NAME = c.CONSTRAINT_NAME
+                        INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS d
+                              ON c.CONSTRAINT_NAME = d.CONSTRAINT_NAME
+                        INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS e
+                              ON a.CONSTRAINT_NAME = e.CONSTRAINT_NAME
+                    WHERE a.TABLE_NAME = ? AND
+                          a.CONSTRAINT_TYPE = 'FOREIGN KEY'"""
+    cursor = Cursor(cursor.db.connection)
+    cursor.execute(sql, (table_name,))
+    return dict([(table_index[item[0]], (_name_to_index(cursor, item[1])[item[2]], item[1]))
+                  for item in cursor.fetchall()])
+    
+def get_indexes(cursor, table_name):
+    """
+    Returns a dictionary of fieldname -> infodict for the given table,
+    where each infodict is in the format:
+        {'primary_key': boolean representing whether it's the primary key,
+         'unique': boolean representing whether it's a unique index}
+    """
+    sql = """SELECT b.COLUMN_NAME, a.CONSTRAINT_TYPE
+               FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS a INNER JOIN
+                    INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS b
+                    ON a.CONSTRAINT_NAME = b.CONSTRAINT_NAME AND
+                       a.TABLE_NAME = b.TABLE_NAME
+               WHERE a.TABLE_NAME = ? AND
+                     (CONSTRAINT_TYPE = 'PRIMARY KEY' OR
+                      CONSTRAINT_TYPE = 'UNIQUE')"""
+    field_names = [item[0] for item in get_table_description(cursor, table_name, identity_check=False)]
+    cursor = Cursor(cursor.db.connection)
+    cursor.execute(sql, (table_name,))
+    indexes = {}
+    results = {}
+    data = cursor.fetchall()
+    if data:
+        results.update(data)
+    for field in field_names:
+        val = results.get(field, None)
+        indexes[field] = dict(primary_key=(val=='PRIMARY KEY'), unique=(val=='UNIQUE'))
+    return indexes
+
+# A reference for the values below:
+# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/mdcstdatatypeenum.asp
+DATA_TYPES_REVERSE = {
+# 8192 : Array ,
+# 128 : Binary ,
+# 9 : IDispatch ,
+# 12 : Variant ,
+# 13 : IUnknown ,
+# 21  : UnsignedBigInt,
+# 132 : UserDefined ,
+# 0   : Empty ,
+# 136 : Chapter ,
+# 138 : PropVariant ,
+# 204 : VarBinary ,
+# 205 : LongVarBinary ,
+-777: 'AutoField',                  # Custom number used to identify AutoFields
+2   : 'SmallIntegerField',          # SmallInt
+3   : 'IntegerField',               # Integer
+4   : 'FloatField',                 # Single
+5   : 'FloatField',                 # Decimal
+6   : 'FloatField',                 # Currency
+7   : 'DateField',                  # Date
+8   : 'CharField',                  # BSTR
+10  : 'IntegerField',               # Error
+11  : 'BooleanField',               # Boolean
+14  : 'FloatField',                 # Decimal
+16  : 'SmallIntegerField',          # TinyInt
+17  : 'PositiveSmallIntegerField',  # UnsignedTinyInt
+18  : 'PositiveSmallIntegerField',  # UnsignedSmallInt
+19  : 'PositiveIntegerField',       # UnsignedInt
+20  : 'IntegerField',               # BigInt
+64  : 'DateTimeField',              # FileTime
+72  : 'CharField',                  # GUID
+129 : 'CharField',                  # Char
+130 : 'CharField',                  # WChar
+131 : 'FloatField',                 # Numeric
+133 : 'DateField',                  # DBDate
+134 : 'TimeField',                  # DBTime
+135 : 'DateTimeField',              # DBTimeStamp
+139 : 'FloatField',                 # VarNumeric
+200 : 'CharField',                  # VarChar
+201 : 'TextField',                  # LongVarChar
+202 : 'CharField',                  # VarWChar
+203 : 'TextField',                  # LongVarWChar
+}
\ No newline at end of file
Index: db/backends/util.py
===================================================================
--- db/backends/util.py	(revision 5596)
+++ db/backends/util.py	(working copy)
@@ -1,3 +1,4 @@
+from django.conf import settings
 import datetime
 import md5
 from time import time
@@ -22,8 +23,24 @@
             # formatting with '%' only works with tuples or dicts.
             if not isinstance(params, (tuple, dict)):
                 params = tuple(params)
+            # ado_mssql uses '?' for parameter escaping, so all '?'
+            # must be replaced with the standard '%s' if the parameter
+            # substitution is going to work.
+            if settings.DATABASE_ENGINE == 'ado_mssql':
+                sql = sql.replace('?', '%s')
+            # There are many situations that will cause the string
+            # substituion below to fail (e.g. wildcard characters '%'
+            # in LIKE queries).  Instead of attempting to figure out
+            # the many variations that can cause an error, the string substition
+            # will be attempted first; if it fails, then the sql
+            # and its parameters will be combined into a string similar to
+            # the one created in the executemany function below.
+            try:
+                sql = sql % tuple(params)
+            except:
+                sql = '%s SQL: %s' % (sql, str(tuple(params)))
             self.db.queries.append({
-                'sql': sql % params,
+                'sql': sql,
                 'time': "%.3f" % (stop - start),
             })
 
Index: db/models/base.py
===================================================================
--- db/models/base.py	(revision 5596)
+++ db/models/base.py	(working copy)
@@ -239,9 +239,22 @@
                     (backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.order_with_respect_to.column)))
                 db_values.append(getattr(self, self._meta.order_with_respect_to.attname))
             if db_values:
+                if pk_set and (settings.DATABASE_ENGINE=="ado_mssql" or settings.DATABASE_ENGINE=="mssql"):
+                    # You can't insert an auto value into a column unless you do
+                    # this in MSSQL
+                    # TODO: Only works for auto-id's... how chek it properly?
+                    if self._meta.pk.column == 'id':
+                        cursor.execute("SET IDENTITY_INSERT %s ON" % \
+                            backend.quote_name(self._meta.db_table))
+                    
                 cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % \
                     (backend.quote_name(self._meta.db_table), ','.join(field_names),
                     ','.join(placeholders)), db_values)
+                    
+                if pk_set and (settings.DATABASE_ENGINE=="ado_mssql" or settings.DATABASE_ENGINE=="mssql"):
+                    if self._meta.pk.column == 'id':
+                        cursor.execute("SET IDENTITY_INSERT %s OFF" %\
+                            backend.quote_name(self._meta.db_table))
             else:
                 # Create a new record with defaults for everything.
                 cursor.execute("INSERT INTO %s (%s) VALUES (%s)" %
Index: db/models/fields/__init__.py
===================================================================
--- db/models/fields/__init__.py	(revision 5596)
+++ db/models/fields/__init__.py	(working copy)
@@ -193,7 +193,7 @@
                 value = int(value)
             except ValueError:
                 raise ValueError("The __year lookup type requires an integer argument")
-            return ['%s-01-01 00:00:00' % value, '%s-12-31 23:59:59.999999' % value]
+            return ['%s-01-01 00:00:00' % value, '%s-12-31 23:59:59.99' % value]
         raise TypeError("Field has invalid lookup: %s" % lookup_type)
 
     def has_default(self):
@@ -541,12 +541,15 @@
         if value is not None:
             # MySQL will throw a warning if microseconds are given, because it
             # doesn't support microseconds.
-            if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'):
+            if settings.DATABASE_ENGINE in ('mysql', 'ado_mssql','mssql') and hasattr(value, 'microsecond'):
                 value = value.replace(microsecond=0)
             value = str(value)
         return Field.get_db_prep_save(self, value)
 
     def get_db_prep_lookup(self, lookup_type, value):
+        # MSSQL doesn't like microseconds.
+        if settings.DATABASE_ENGINE in ('mysql', 'ado_mssql','mssql') and hasattr(value, 'microsecond'):
+            value = value.replace(microsecond=0)
         if lookup_type == 'range':
             value = [str(v) for v in value]
         else:
@@ -908,8 +911,9 @@
         # Casts dates into string format for entry into database.
         if value is not None:
             # MySQL will throw a warning if microseconds are given, because it
-            # doesn't support microseconds.
-            if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'):
+            # doesn't support microseconds. Ditto MSSQL
+            if settings.DATABASE_ENGINE in ('mysql', 'ado_mssql','mssql') \
+                            and hasattr(value, 'microsecond'):
                 value = value.replace(microsecond=0)
             if settings.DATABASE_ENGINE == 'oracle':
                 # cx_Oracle expects a datetime.datetime to persist into TIMESTAMP field.
