Index: db/models/base.py
===================================================================
--- db/models/base.py	(r‚vision 5986)
+++ db/models/base.py	(copie de travail)
@@ -246,9 +246,22 @@
                     (qn(self._meta.db_table), qn(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" % \
+                            qn(self._meta.db_table))
+                    
                 cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % \
                     (qn(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" %\
+                            qn(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	(r‚vision 5986)
+++ db/models/fields/__init__.py	(copie de travail)
@@ -223,7 +223,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):
@@ -574,12 +574,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 = smart_unicode(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 = [smart_unicode(v) for v in value]
         else:
@@ -966,8 +969,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.
Index: db/backends/mssql/base.py
===================================================================
--- db/backends/mssql/base.py	(r‚vision 0)
+++ db/backends/mssql/base.py	(r‚vision 0)
@@ -0,0 +1,464 @@
+"""
+Alpha Multi-plataform MSSQL database backend for Django.
+
+Requires pymssql >= v0.8.0: http://pymssql.sourceforge.net/
+"""
+
+import datetime
+from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, 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
+
+class DatabaseFeatures(BaseDatabaseFeatures):
+	pass
+
+class DatabaseOperations(BaseDatabaseOperations):
+    def last_insert_id(self, 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 query_set_class(self, DefaultQuerySet):
+	    "Create a custom QuerySet class for SqlServer."
+	
+	    from django.db import 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
+	            qn = connection.ops.quote_name
+	
+	            # Construct the fundamental parts of the query: SELECT X FROM Y WHERE Z.
+	            select = ["%s.%s" % (qn(opts.db_table), qn(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]), qn(s[0])) for s in self._select.items()])
+	
+	            # Start composing the body of the SQL statement.
+	            sql = [" FROM", qn(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(connection.ops.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 = qn(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 = qn(opts.db_table) + '.'
+	                        else:
+	                            table_prefix = ''
+	                    order_by.append('%s%s %s' % (table_prefix, qn(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] = qn(col)
+	                    select[index] = '%s AS %s' % (select[index], qn(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' %
+	                        (qn(opts.db_table),
+	                        qn(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':qn(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
+    
+    def date_extract_sql(self, lookup_type, field_name):
+		# lookup_type is 'year', 'month', 'day'
+		return "DATEPART(%s, %s)" % (lookup_type, table_name)
+
+    def date_trunc_sql(self, 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 limit_offset_sql(self, limit, offset=None):
+		# Limits and offset are too complicated to be handled here.
+		# Look for a implementation similar to SqlServer backend
+		return ""
+
+    def quote_name(self, name):
+        if name.startswith('[') and name.endswith(']'):
+        	return name # Quoting once is enough.
+        return '[%s]' % name
+
+    def random_function_sql(self):
+        return "RAND()"
+       
+    def tablespace_sql(self, tablespace, inline=False):
+     return "ON %s" % quote_name(tablespace)
+
+    def sql_flush(self, style, tables, 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 referenced by a FOREIGN KEY
+		# So must use the much slower DELETE
+		from django.db import connection
+		cursor = connection.cursor()
+		cursor.execute("SELECT TABLE_NAME, CONSTRAINT_NAME FROM information_schema.table_constraints")
+		fks = cursor.fetchall()
+		sql_list = ['ALTER TABLE %s NOCHECK CONSTRAINT %s;' % \
+				(self.quote_name(fk[0]), self.quote_name(fk[1])) for fk in fks]
+		sql_list.extend(['%s %s %s;' % \
+					(style.SQL_KEYWORD('DELETE'),
+					style.SQL_KEYWORD('FROM'),
+					style.SQL_FIELD(self.quote_name(table))
+					)  for table in tables])
+		#The reset the counters on each table.
+		sql_list.extend(['%s %s (%s, %s, %s) %s %s;' % (
+			style.SQL_KEYWORD('DBCC'),
+			style.SQL_KEYWORD('CHECKIDENT'),
+			style.SQL_FIELD(self.quote_name(seq["table"])),
+			style.SQL_KEYWORD('RESEED'),
+			style.SQL_FIELD('1'),
+			style.SQL_KEYWORD('WITH'),
+			style.SQL_KEYWORD('NO_INFOMSGS'),
+			) for seq in sequences])
+		sql_list.extend(['ALTER TABLE %s CHECK CONSTRAINT %s;' % \
+				(self.quote_name(fk[0]), self.quote_name(fk[1])) for fk in fks])
+		return sql_list 
+
+
+
+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(BaseDatabaseWrapper):
+    features = DatabaseFeatures() 
+    ops = DatabaseOperations()
+    operators = {
+	    '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',
+	}
+    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])
+
+
+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
\ Pas de fin de ligne … la fin du fichier
Index: db/backends/mssql/client.py
===================================================================
--- db/backends/mssql/client.py	(r‚vision 0)
+++ db/backends/mssql/client.py	(r‚vision 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
===================================================================
--- db/backends/mssql/__init__.py	(r‚vision 0)
+++ db/backends/mssql/__init__.py	(r‚vision 0)
@@ -0,0 +1 @@
+# placeholder
\ Pas de fin de ligne … la fin du fichier
Index: db/backends/mssql/introspection.py
===================================================================
--- db/backends/mssql/introspection.py	(r‚vision 0)
+++ db/backends/mssql/introspection.py	(r‚vision 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
+}
\ Pas de fin de ligne … la fin du fichier
Index: db/backends/mssql/creation.py
===================================================================
--- db/backends/mssql/creation.py	(r‚vision 0)
+++ db/backends/mssql/creation.py	(r‚vision 0)
@@ -0,0 +1,27 @@
+DATA_TYPES = {
+    'AutoField':         'int IDENTITY (1, 1)',
+    'BooleanField':      'bit',
+    'CharField':         'varchar(%(max_length)s)',
+    'CommaSeparatedIntegerField': 'varchar(%(max_length)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(%(max_length)s)',
+    'SmallIntegerField': 'smallint',
+    'TextField':         'text',
+    'TimeField':         'datetime',
+    'USStateField':      'varchar(2)',
+}
Index: db/backends/util.py
===================================================================
--- db/backends/util.py	(r‚vision 5986)
+++ db/backends/util.py	(copie de travail)
@@ -1,3 +1,4 @@
+from django.conf import settings
 import datetime
 import md5
 from time import time
Index: contrib/sessions/middleware.py
===================================================================
--- contrib/sessions/middleware.py	(r‚vision 5986)
+++ contrib/sessions/middleware.py	(copie de travail)
@@ -61,8 +61,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 = {}
