aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/ota/sqlite3ota.c55
-rw-r--r--manifest16
-rw-r--r--manifest.uuid2
-rw-r--r--src/sqlite.h.in1
-rw-r--r--src/vdbeblob.c96
5 files changed, 126 insertions, 44 deletions
diff --git a/ext/ota/sqlite3ota.c b/ext/ota/sqlite3ota.c
index fcf0c8b9f..aca28e2e3 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 344ec70e0..9496fcd9a 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 8423c49a1..4e033cd4f 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 7011b67fd..b543f1345 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 09c519cb5..4ecd56522 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);