diff --git a/ext/ota/sqlite3ota.c b/ext/ota/sqlite3ota.c
index fcf0c8b9fd..aca28e2e3b 100644
--- a/ext/ota/sqlite3ota.c
+++ b/ext/ota/sqlite3ota.c
@@ -401,11 +401,46 @@ static int otaObjIterGetCols(sqlite3ota *p, OtaObjIter *pIter){
   return p->rc;
 }
 
+/*
+** This function constructs and returns a pointer to a nul-terminated 
+** string containing some SQL clause or list based on one or more of the 
+** column names currently stored in the pIter->azTblCol[] array.
+**
+** If an OOM error is encountered, NULL is returned and an error code
+** left in the OTA handle passed as the first argument. Otherwise, a pointer
+** to the allocated string buffer is returned. It is the responsibility
+** of the caller to eventually free this buffer using sqlite3_free().
+**
+** The number of column names to include in the returned string is passed
+** as the third argument.
+**
+** If arguments aiCol and azCollate are both NULL, then the returned string
+** contains the first nCol column names as a comma-separated list. For 
+** example:
+**
+**     "a", "b", "c"
+**
+** If argument aiCol is not NULL, it must point to an array containing nCol
+** entries - the index of each column name to include in the comma-separated
+** list. For example, if aiCol[] contains {2, 0, 1), then the returned 
+** string is changed to:
+**
+**     "c", "a", "b"
+**
+** If azCollate is not NULL, it must also point to an array containing nCol
+** entries - collation sequence names to associated with each element of
+** the comma separated list. For example, ef azCollate[] contains 
+** {"BINARY", "NOCASE", "REVERSE"}, then the retuned string is:
+**
+**     "c" COLLATE "BINARY", "a" COLLATE "NOCASE", "b" COLLATE "REVERSE"
+**
+*/
 static char *otaObjIterGetCollist(
-  sqlite3ota *p, 
-  OtaObjIter *pIter, 
-  int nCol, 
-  int *aiCol
+  sqlite3ota *p,                  /* OTA object */
+  OtaObjIter *pIter,              /* Object iterator for column names */
+  int nCol,                       /* Number of column names */
+  int *aiCol,                     /* Array of nCol column indexes */
+  const char **azCollate          /* Array of nCol collation sequence names */
 ){
   char *zList = 0;
   if( p->rc==SQLITE_OK ){
@@ -414,6 +449,9 @@ static char *otaObjIterGetCollist(
     for(i=0; i<nCol; i++){
       int iCol = aiCol ? aiCol[i] : i;
       zList = sqlite3_mprintf("%z%s%s", zList, zSep, pIter->azTblCol[iCol]);
+      if( zList && azCollate ){
+        zList = sqlite3_mprintf("%z COLLATE %Q", zList, azCollate[i]);
+      }
       zSep = ", ";
       if( zList==0 ){
         p->rc = SQLITE_NOMEM;
@@ -548,21 +586,22 @@ static int otaObjIterPrepareAll(
 
     if( zIdx ){
       int *aiCol;                 /* Column map */
+      const char **azColl;        /* Collation sequences */
 
       /* Create the index writers */
       if( p->rc==SQLITE_OK ){
         p->rc = sqlite3_index_writer(
-            p->db, 0, zIdx, &pIter->pInsert, &aiCol, &pIter->nCol
+            p->db, 0, zIdx, &pIter->pInsert, &azColl, &aiCol, &pIter->nCol
         );
       }
       if( p->rc==SQLITE_OK ){
         p->rc = sqlite3_index_writer(
-            p->db, 1, zIdx, &pIter->pDelete, &aiCol, &pIter->nCol
+            p->db, 1, zIdx, &pIter->pDelete, &azColl, &aiCol, &pIter->nCol
         );
       }
 
       /* Create the SELECT statement to read keys in sorted order */
-      zCollist = otaObjIterGetCollist(p, pIter, pIter->nCol, aiCol);
+      zCollist = otaObjIterGetCollist(p, pIter, pIter->nCol, aiCol, azColl);
       if( p->rc==SQLITE_OK ){
         p->rc = prepareFreeAndCollectError(p->db, &pIter->pSelect, pz,
             sqlite3_mprintf(
@@ -582,7 +621,7 @@ static int otaObjIterPrepareAll(
       char *zWhere = otaObjIterGetWhere(p, pIter);
       char *zOldlist = otaObjIterGetOldlist(p, pIter, "old");
       char *zNewlist = otaObjIterGetOldlist(p, pIter, "new");
-      zCollist = otaObjIterGetCollist(p, pIter, pIter->nTblCol, 0);
+      zCollist = otaObjIterGetCollist(p, pIter, pIter->nTblCol, 0, 0);
       pIter->nCol = pIter->nTblCol;
 
       /* Create the SELECT statement to read keys from data_xxx */
diff --git a/manifest b/manifest
index 344ec70e00..9496fcd9a5 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Have\sthe\ssqlite3_index_writer()\sVMs\scheck\sthat\sthe\sfinal\svalues\sof\srecords\sinserted\sinto\sindexes\son\srowid\stables\sare\sintegers.
-D 2014-09-15T12:18:29.913
+C Ensure\sthe\scorrect\scollation\ssequences\sare\sused\swhen\ssorting\sdata\sin\ssqlite3ota.c.
+D 2014-09-15T14:54:07.328
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -125,7 +125,7 @@ F ext/ota/ota.c d37097e92a005d3915883adefbb93019ea6f8841
 F ext/ota/ota1.test fe0bb8acf0caef6c19937b84c6547b788342610d
 F ext/ota/ota2.test 13f76922446c62ed96192e938b8e625ebf0142fa
 F ext/ota/ota3.test 7179a90eb64cf8135a6885568653f158fb130872
-F ext/ota/sqlite3ota.c 3697f6db2d51d5f7c0f0306fe94514785361e521
+F ext/ota/sqlite3ota.c c29b3eb617f37d0e51744508b8f609014244727d
 F ext/ota/sqlite3ota.h 39ce4dffbfcf4ade9e4526369fe2243709345c8e
 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
 F ext/rtree/rtree.c 57bec53e1a677ab74217fe1f20a58c3a47261d6b
@@ -231,7 +231,7 @@ F src/resolve.c 0ea356d32a5e884add23d1b9b4e8736681dd5697
 F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be
 F src/select.c 89e569b263535662f54b537eb9118b2c554ae7aa
 F src/shell.c 713cef4d73c05fc8e12f4960072329d767a05d50
-F src/sqlite.h.in 706b420dc3390532435a3bd196360a940805f02f
+F src/sqlite.h.in 578c42cb3899ee6ad93a0cccff4eb47e1e9a2c80
 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
 F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
 F src/sqliteInt.h 7c090825333d91ca392c2479a9e835e7b6a5eb12
@@ -296,7 +296,7 @@ F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8
 F src/vdbeInt.h cdc8e421f85beb1ac9b4669ec5beadab6faa15e0
 F src/vdbeapi.c 09677a53dd8c71bcd670b0bd073bb9aefa02b441
 F src/vdbeaux.c cef5d34a64ae3a65b56d96d3fd663246ec8e1c36
-F src/vdbeblob.c 7ddae314db27c39f654fd2af577c9afc33d089d9
+F src/vdbeblob.c a8e2c3baa3e7081347c4677185a631bfc43de043
 F src/vdbemem.c 921d5468a68ac06f369810992e84ca22cc730a62
 F src/vdbesort.c 7c45bfcd823f30d172bbbc1b9f51ef4402fbfe8d
 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
@@ -1199,7 +1199,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P b9b38cb8e21826ddfb4c87a1f166ad33c3c7b6eb
-R 6282c8b629d24290f7b2f44befcb6a71
+P cca376bff3510dc5e99fc5824862c3471ceced16
+R 286b5daf6c561394d2eea11438cdac48
 U dan
-Z 32d433205c33319cd81cbc2b152b81af
+Z e26ad3cda7162cfc9e1d6f5aeb5cd971
diff --git a/manifest.uuid b/manifest.uuid
index 8423c49a14..4e033cd4fd 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-cca376bff3510dc5e99fc5824862c3471ceced16
\ No newline at end of file
+473a72d7009a22ea514a98ee8869e7e7bca14cf5
\ No newline at end of file
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 7011b67fd4..b543f1345d 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -7415,6 +7415,7 @@ int sqlite3_index_writer(
   int bDelete,                    /* Zero for insert, non-zero for delete */
   const char *zIndex,             /* Index to write to */
   sqlite3_stmt**,                 /* OUT: New statement handle */
+  const char ***pazColl,          /* OUT: Collation sequences for each column */
   int **paiCol, int *pnCol        /* OUT: See above */
 );
 
diff --git a/src/vdbeblob.c b/src/vdbeblob.c
index 09c519cb59..4ecd56522f 100644
--- a/src/vdbeblob.c
+++ b/src/vdbeblob.c
@@ -463,12 +463,77 @@ int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
   return rc;
 }
 
+static int indexWriterOutputVars(
+  sqlite3 *db,
+  Index *pIdx,
+  const char ***pazColl,          /* OUT: Array of collation sequences */
+  int **paiCol,                   /* OUT: Array of column indexes */
+  int *pnCol                      /* OUT: Total columns in index keys */
+){
+  Table *pTbl = pIdx->pTable;     /* Table index is attached to */
+  Index *pPk = 0;
+  int nByte = 0;                  /* Total bytes of space to allocate */
+  int i;                          /* Iterator variable */
+
+  int *aiCol;
+  const char **azColl;
+  char *pCsr;
+
+  if( !HasRowid(pTbl) ){
+    pPk = sqlite3PrimaryKeyIndex(pTbl);
+  }
+
+  for(i=0; i<pIdx->nColumn; i++){
+    const char *zColl = 0;
+    if( i<pIdx->nKeyCol ){
+      zColl = pIdx->azColl[i];
+    }else if( pPk ){
+      zColl = pPk->azColl[i-pIdx->nKeyCol];
+    }
+    if( zColl==0 ) zColl = "BINARY";
+    nByte += sqlite3Strlen30(zColl) + 1;
+  }
+  nByte += (pIdx->nColumn) * (sizeof(const char*) + sizeof(int));
+
+  /* Populate the output variables */
+  *pazColl = azColl = (const char**)sqlite3DbMallocZero(db, nByte);
+  if( azColl==0 ) return SQLITE_NOMEM;
+  *paiCol = aiCol = (int*)&azColl[pIdx->nColumn];
+  *pnCol = pIdx->nColumn;
+  pCsr = (char*)&aiCol[pIdx->nColumn];
+
+  for(i=0; i<pIdx->nColumn; i++){
+    const char *zColl = 0;
+    int nColl;
+    int iCol = pTbl->iPKey;
+    if( i<pIdx->nKeyCol ){
+      zColl = pIdx->azColl[i];
+      iCol = pIdx->aiColumn[i];
+    }else if( pPk ){
+      zColl = pPk->azColl[i-pIdx->nKeyCol];
+      iCol = pPk->aiColumn[i-pIdx->nKeyCol];
+    }
+    if( zColl==0 ) zColl = "BINARY";
+
+    aiCol[i] = iCol;
+    azColl[i] = pCsr;
+    nColl = 1 + sqlite3Strlen30(zColl);
+    memcpy(pCsr, zColl, nColl);
+    pCsr += nColl;
+  }
+
+  return SQLITE_OK;
+}
+
+
 int sqlite3_index_writer(
   sqlite3 *db, 
   int bDelete,
   const char *zIndex, 
   sqlite3_stmt **ppStmt,
-  int **paiCol, int *pnCol
+  const char ***pazColl,          /* OUT: Array of collation sequences */
+  int **paiCol,                   /* OUT: Array of column indexes */
+  int *pnCol                      /* OUT: Total columns in index keys */
 ){
   int rc = SQLITE_OK;
   Parse *pParse = 0;
@@ -477,7 +542,6 @@ int sqlite3_index_writer(
   int i;                          /* Used to iterate through index columns */
   Vdbe *v = 0;
   int regRec;                     /* Register to assemble record in */
-  int *aiCol = 0;
   const char *zAffinity = 0;      /* Affinity string for the current index */
 
   sqlite3_mutex_enter(db->mutex);
@@ -502,37 +566,15 @@ int sqlite3_index_writer(
   pTab = pIdx->pTable;
   zAffinity = sqlite3IndexAffinityStr(v, pIdx);
 
-  /* Populate the two output variables, *pnCol and *pnAiCol. */
-  *pnCol = pIdx->nColumn;
-  *paiCol = aiCol = sqlite3DbMallocZero(db, sizeof(int) * pIdx->nColumn);
-  if( aiCol==0 ){
-    rc = SQLITE_NOMEM;
-    goto index_writer_out;
-  }
-  for(i=0; i<pIdx->nKeyCol; i++){
-    aiCol[i] = pIdx->aiColumn[i];
-  }
-  if( !HasRowid(pTab) ){
-    Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
-    assert( pIdx->nColumn==pIdx->nKeyCol+pPk->nKeyCol );
-    if( pPk==pIdx ){
-      rc = SQLITE_ERROR;
-      goto index_writer_out;
-    }
-    for(i=0; i<pPk->nKeyCol; i++){
-      aiCol[pIdx->nKeyCol+i] = pPk->aiColumn[i];
-    }
-  }else{
-    assert( pIdx->nColumn==pIdx->nKeyCol+1 );
-    aiCol[i] = pTab->iPKey;
-  }
+  rc = indexWriterOutputVars(db, pIdx, pazColl, paiCol, pnCol);
+  if( rc!=SQLITE_OK ) goto index_writer_out;
 
   /* Add an OP_Noop to the VDBE program. Then store a pointer to the 
   ** output array *paiCol as its P4 value. This is so that the array
   ** is automatically deleted when the user finalizes the statement. The
   ** OP_Noop serves no other purpose. */
   sqlite3VdbeAddOp0(v, OP_Noop);
-  sqlite3VdbeChangeP4(v, -1, (const char*)aiCol, P4_INTARRAY);
+  sqlite3VdbeChangeP4(v, -1, (const char*)(*pazColl), P4_INTARRAY);
 
   sqlite3BeginWriteOperation(pParse, 0, 0);