mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Add the sqlite3_collation_needed() API and fix some error handling cases
involving unknown collation sequences. (CVS 1562) FossilOrigin-Name: edf069b9f4044ed2a80962c7722052bf1b80bf45
This commit is contained in:
32
manifest
32
manifest
@@ -1,5 +1,5 @@
|
||||
C Misc\sfixes\sfor\stest\scases\sfailing\sdue\sto\sthe\snew\slocking\smodel.\s(CVS\s1561)
|
||||
D 2004-06-10T05:59:25
|
||||
C Add\sthe\ssqlite3_collation_needed()\sAPI\sand\sfix\ssome\serror\shandling\scases\ninvolving\sunknown\scollation\ssequences.\s(CVS\s1562)
|
||||
D 2004-06-10T10:50:08
|
||||
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
||||
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
|
||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||
@@ -27,17 +27,17 @@ F src/attach.c 93b8ecec4a8d7b4e9f2479e2327d90c9d01765e8
|
||||
F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79
|
||||
F src/btree.c 281af87aa117de024f5b6c2728a2339cba9ef584
|
||||
F src/btree.h 589427ac13bb544d298cd99726e2572a6fe4bdaa
|
||||
F src/build.c 5d958f480d71f56981f262de6994a4d2ee6e5f75
|
||||
F src/build.c 4b1a23d919fe01549702f7f1bfe7f8b656e77a17
|
||||
F src/date.c 8e6fa3173386fb29fdef012ee08a853c1e9908b2
|
||||
F src/delete.c b30f08250c9ed53a25a13c7c04599c1e8753992d
|
||||
F src/delete.c 911221aadb35d610c84fadb32e71c52990827e58
|
||||
F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37
|
||||
F src/expr.c 3aea8faac17debea4f5c2659351c27d5660453a0
|
||||
F src/expr.c 34e63e960ab8ca9e4fc4a1f41b0a3b77df2ae167
|
||||
F src/func.c ffbdfa4cad2a16a41390c2ce923ef8b0f173d777
|
||||
F src/hash.c 440c2f8cb373ee1b4e13a0988489c7cd95d55b6f
|
||||
F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb
|
||||
F src/insert.c 4268d9e3959cc845ea243fb4ec7507269404dad9
|
||||
F src/insert.c 68c7f3ddd6a7f1e5596d6996da1a2861b3789a3a
|
||||
F src/legacy.c ad23746f15f67e34577621b1875f639c94839e1f
|
||||
F src/main.c cb41777e75f6b95a2af42f439c78e761a49cdffa
|
||||
F src/main.c 335b4cd48af0011017e33a411aea307553114e67
|
||||
F src/md5.c 4302e84ae516c616bb079c4e6d038c0addb33481
|
||||
F src/os.h 23c69c5084e71b5fe199ff1c4e35a4aded0f1380
|
||||
F src/os_common.h 6393ac67a3a7b4aea19ff17529980ecf77eb2348
|
||||
@@ -50,15 +50,15 @@ F src/os_win.h 004eec47b1780fcaf07420ddc2072294b698d48c
|
||||
F src/pager.c d852730901441babf6cd16fc528dd6eecc2b2eab
|
||||
F src/pager.h ca8f293e1d623a7c628a1c5e0c6cf43d5bbb80bf
|
||||
F src/parse.y 097438674976355a10cf177bd97326c548820b86
|
||||
F src/pragma.c 6ab13748a415bf8e8f2dd79e5f713fbe72dfd3f4
|
||||
F src/pragma.c 0bc3adea28df802074996bec067d506d55d28f84
|
||||
F src/printf.c 63b15f1ea9fe3daa066bb7430fd20d4a2d717dc8
|
||||
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
|
||||
F src/select.c 1f8355e702f109f6771f82a9bfe7aac4c82cbaf2
|
||||
F src/select.c 6cb407796dde0e8f27450ead68856eb9f8188789
|
||||
F src/shell.c ca519519dcbbc582f6d88f7d0e7583b857fd3469
|
||||
F src/sqlite.h.in 00ce6b80cf4dffa9bf7a028d80d1ffba708b175a
|
||||
F src/sqliteInt.h cd9db5ca4a2ba59cf1692fcbd1ea7318c50f0c4f
|
||||
F src/sqlite.h.in 2b6afe1de6935d3dfbd6042f46a62f1b7c3b3992
|
||||
F src/sqliteInt.h 6be535d420f99c57f29f13c3c2d6a3497432b366
|
||||
F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2
|
||||
F src/tclsqlite.c 6383ba7b620b276d49b40d48872502e0adb1b685
|
||||
F src/tclsqlite.c e974c0b2479ed37334aeb268de331e0a1b21b5a8
|
||||
F src/test1.c f78d6ac0675bc5db48dac9c5379c965bdadb9113
|
||||
F src/test2.c 05f810c90cf6262d5f352860e87d41a3f34207f9
|
||||
F src/test3.c beafd0ccf7b9ae784744be1b1e66ffe8f64c25da
|
||||
@@ -66,7 +66,7 @@ F src/test4.c a921a69821fd30209589228e64f94e9f715b6fe2
|
||||
F src/test5.c 862784cd7a68e7d36f00287aac6e413ca996eaf8
|
||||
F src/tokenize.c 183c5d7da11affab5d70d903d33409c8c0ce6c5b
|
||||
F src/trigger.c d1a4d7a59b34c811bf6070d64d0497baa0140dcf
|
||||
F src/update.c 259f06e7b22c684b2d3dda54a18185892d6e9573
|
||||
F src/update.c 168b6d523087ca4545b74ec9f3102b1f3c6b1e38
|
||||
F src/utf.c c2c8e445bfea724f3502609d6389fe66651f02ab
|
||||
F src/util.c e8629f04d920ae968fced709dc7a3a2c62b65ac4
|
||||
F src/vacuum.c b921eb778842592e1fb48a9d4cef7e861103878f
|
||||
@@ -218,7 +218,7 @@ F www/support.tcl 1801397edd271cc39a2aadd54e701184b5181248
|
||||
F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075
|
||||
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
|
||||
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
||||
P adb2bd61436927d37b23bae857089d62e12397af
|
||||
R e8b127567100f827cb21e845b744b7ae
|
||||
P 71e98d0d089576433c4b06dcba1c57063bd366f5
|
||||
R 3d4ef809458f49528c446bf513dcad92
|
||||
U danielk1977
|
||||
Z 7c95f2d087a4836fb9faba67d8f7b64b
|
||||
Z b84856b016de718871cfb8d15d69b3b5
|
||||
|
@@ -1 +1 @@
|
||||
71e98d0d089576433c4b06dcba1c57063bd366f5
|
||||
edf069b9f4044ed2a80962c7722052bf1b80bf45
|
166
src/build.c
166
src/build.c
@@ -23,7 +23,7 @@
|
||||
** ROLLBACK
|
||||
** PRAGMA
|
||||
**
|
||||
** $Id: build.c,v 1.214 2004/06/10 02:16:02 danielk1977 Exp $
|
||||
** $Id: build.c,v 1.215 2004/06/10 10:50:08 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@@ -884,7 +884,8 @@ static CollSeq * findCollSeqEntry(
|
||||
pColl[1].enc = TEXT_Utf16le;
|
||||
pColl[2].zName = (char*)&pColl[3];
|
||||
pColl[2].enc = TEXT_Utf16be;
|
||||
memcpy(pColl[0].zName, zName, nName+1);
|
||||
memcpy(pColl[0].zName, zName, nName);
|
||||
pColl[0].zName[nName] = 0;
|
||||
sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl);
|
||||
}
|
||||
}
|
||||
@@ -922,6 +923,110 @@ CollSeq *sqlite3FindCollSeq(
|
||||
return pColl;
|
||||
}
|
||||
|
||||
static void callCollNeeded(sqlite *db, const char *zName, int nName){
|
||||
/* No collation sequence of this type for this encoding is registered.
|
||||
** Call the collation factory to see if it can supply us with one.
|
||||
*/
|
||||
char *zExternal = 0;
|
||||
assert( !db->xCollNeeded || !db->xCollNeeded16 );
|
||||
if( nName<0 ) nName = strlen(zName);
|
||||
if( db->xCollNeeded ){
|
||||
zExternal = sqliteStrNDup(zName, nName);
|
||||
if( !zExternal ) return;
|
||||
db->xCollNeeded(db->pCollNeededArg, db, (int)db->enc, zExternal);
|
||||
}
|
||||
if( db->xCollNeeded16 ){
|
||||
if( SQLITE_BIGENDIAN ){
|
||||
zExternal = sqlite3utf8to16be(zName, nName);
|
||||
}else{
|
||||
zExternal = sqlite3utf8to16le(zName, nName);
|
||||
}
|
||||
if( !zExternal ) return;
|
||||
db->xCollNeeded16(db->pCollNeededArg, db, (int)db->enc, zExternal);
|
||||
}
|
||||
if( zExternal ) sqliteFree(zExternal);
|
||||
}
|
||||
|
||||
static int synthCollSeq(Parse *pParse, CollSeq *pColl){
|
||||
/* The collation factory failed to deliver a function but there may be
|
||||
** other versions of this collation function (for other text encodings)
|
||||
** available. Use one of these instead. Avoid a UTF-8 <-> UTF-16
|
||||
** conversion if possible.
|
||||
*/
|
||||
CollSeq *pColl2 = 0;
|
||||
char *z = pColl->zName;
|
||||
int n = strlen(z);
|
||||
switch( pParse->db->enc ){
|
||||
case TEXT_Utf16le:
|
||||
pColl2 = sqlite3FindCollSeq(pParse->db, TEXT_Utf16be, z, n, 0);
|
||||
assert( pColl2 );
|
||||
if( pColl2->xCmp ) break;
|
||||
pColl2 = sqlite3FindCollSeq(pParse->db, TEXT_Utf8, z, n, 0);
|
||||
assert( pColl2 );
|
||||
break;
|
||||
|
||||
case TEXT_Utf16be:
|
||||
pColl2 = sqlite3FindCollSeq(pParse->db,TEXT_Utf16le, z, n, 0);
|
||||
assert( pColl2 );
|
||||
if( pColl2->xCmp ) break;
|
||||
pColl2 = sqlite3FindCollSeq(pParse->db,TEXT_Utf8, z, n, 0);
|
||||
assert( pColl2 );
|
||||
break;
|
||||
|
||||
case TEXT_Utf8:
|
||||
pColl2 = sqlite3FindCollSeq(pParse->db,TEXT_Utf16be, z, n, 0);
|
||||
assert( pColl2 );
|
||||
if( pColl2->xCmp ) break;
|
||||
pColl2 = sqlite3FindCollSeq(pParse->db,TEXT_Utf16le, z, n, 0);
|
||||
assert( pColl2 );
|
||||
break;
|
||||
}
|
||||
if( pColl2->xCmp ){
|
||||
memcpy(pColl, pColl2, sizeof(CollSeq));
|
||||
}else{
|
||||
if( pParse->nErr==0 ){
|
||||
sqlite3SetNString(&pParse->zErrMsg, "no such collation sequence: ",
|
||||
-1, z, n, 0);
|
||||
}
|
||||
pParse->nErr++;
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine is called on a collation sequence before it is used to
|
||||
** check that it is defined. An undefined collation sequence exists when
|
||||
** a database is loaded that contains references to collation sequences
|
||||
** that have not been defined by sqlite3_create_collation() etc.
|
||||
**
|
||||
** If required, this routine calls the 'collation needed' callback to
|
||||
** request a definition of the collating sequence. If this doesn't work,
|
||||
** an equivalent collating sequence that uses a text encoding different
|
||||
** from the main database is substituted, if one is available.
|
||||
*/
|
||||
int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
|
||||
if( pColl && !pColl->xCmp ){
|
||||
callCollNeeded(pParse->db, pColl->zName, strlen(pColl->zName));
|
||||
if( !pColl->xCmp && synthCollSeq(pParse, pColl) ){
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
int sqlite3CheckIndexCollSeq(Parse *pParse, Index *pIdx){
|
||||
if( pIdx ){
|
||||
int i;
|
||||
for(i=0; i<pIdx->nColumn; i++){
|
||||
if( sqlite3CheckCollSeq(pParse, pIdx->keyInfo.aColl[i]) ){
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function returns the collation sequence for database native text
|
||||
** encoding identified by the string zName, length nName.
|
||||
@@ -938,64 +1043,33 @@ CollSeq *sqlite3FindCollSeq(
|
||||
*/
|
||||
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){
|
||||
u8 enc = pParse->db->enc;
|
||||
CollSeq *pColl = sqlite3FindCollSeq(pParse->db, enc, zName, nName, 0);
|
||||
if( !pColl || !pColl->xCmp ){
|
||||
u8 initbusy = pParse->db->init.busy;
|
||||
CollSeq *pColl = sqlite3FindCollSeq(pParse->db, enc, zName, nName, initbusy);
|
||||
if( !initbusy && (!pColl || !pColl->xCmp) ){
|
||||
/* No collation sequence of this type for this encoding is registered.
|
||||
** Call the collation factory to see if it can supply us with one.
|
||||
*/
|
||||
|
||||
/* FIX ME: Actually call collation factory, then call
|
||||
** sqlite3FindCollSeq() again. */
|
||||
callCollNeeded(pParse->db, zName, nName);
|
||||
pColl = sqlite3FindCollSeq(pParse->db, enc, zName, nName, 0);
|
||||
|
||||
if( pColl && !pColl->xCmp ){
|
||||
/* The collation factory failed to deliver a function but there are
|
||||
** other versions of this collation function (for other text
|
||||
** encodings) available. Use one of these instead. Avoid a
|
||||
** UTF-8 <-> UTF-16 conversion if possible.
|
||||
/* There may be a version of the collation sequence that requires
|
||||
** translation between encodings. Search for it with synthCollSeq().
|
||||
*/
|
||||
CollSeq *pColl2 = 0;
|
||||
switch( enc ){
|
||||
case TEXT_Utf16le:
|
||||
pColl2 = sqlite3FindCollSeq(pParse->db,TEXT_Utf16be,zName,nName,0);
|
||||
assert( pColl2 );
|
||||
if( pColl2->xCmp ) break;
|
||||
pColl2 = sqlite3FindCollSeq(pParse->db,TEXT_Utf8,zName,nName,0);
|
||||
assert( pColl2 );
|
||||
break;
|
||||
|
||||
case TEXT_Utf16be:
|
||||
pColl2 = sqlite3FindCollSeq(pParse->db,TEXT_Utf16le,zName,nName,0);
|
||||
assert( pColl2 );
|
||||
if( pColl2->xCmp ) break;
|
||||
pColl2 = sqlite3FindCollSeq(pParse->db,TEXT_Utf8,zName,nName,0);
|
||||
assert( pColl2 );
|
||||
break;
|
||||
|
||||
case TEXT_Utf8:
|
||||
pColl2 = sqlite3FindCollSeq(pParse->db,TEXT_Utf16be,zName,nName,0);
|
||||
assert( pColl2 );
|
||||
if( pColl2->xCmp ) break;
|
||||
pColl2 = sqlite3FindCollSeq(pParse->db,TEXT_Utf16le,zName,nName,0);
|
||||
assert( pColl2 );
|
||||
break;
|
||||
}
|
||||
|
||||
if( pColl2->xCmp ){
|
||||
memcpy(pColl, pColl2, sizeof(CollSeq));
|
||||
if( synthCollSeq(pParse, pColl) ){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If nothing has been found, write the error message into pParse */
|
||||
if( !pColl || !pColl->xCmp ){
|
||||
if( !initbusy && (!pColl || !pColl->xCmp) ){
|
||||
if( pParse->nErr==0 ){
|
||||
sqlite3SetNString(&pParse->zErrMsg, "no such collation sequence: ", -1,
|
||||
zName, nName, 0);
|
||||
}
|
||||
pParse->nErr++;
|
||||
pColl = 0;
|
||||
}
|
||||
|
||||
return pColl;
|
||||
}
|
||||
|
||||
@@ -1943,6 +2017,11 @@ void sqlite3CreateIndex(
|
||||
pIndex->keyInfo.aColl[i] = pTab->aCol[j].pColl;
|
||||
}
|
||||
assert( pIndex->keyInfo.aColl[i] );
|
||||
if( !db->init.busy &&
|
||||
sqlite3CheckCollSeq(pParse, pIndex->keyInfo.aColl[i])
|
||||
){
|
||||
goto exit_create_index;
|
||||
}
|
||||
}
|
||||
pIndex->keyInfo.nField = pList->nExpr;
|
||||
|
||||
@@ -2448,7 +2527,6 @@ void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
|
||||
** specified auxiliary database and the temp database are made writable.
|
||||
*/
|
||||
void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
|
||||
sqlite *db = pParse->db;
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
if( v==0 ) return;
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
|
@@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle DELETE FROM statements.
|
||||
**
|
||||
** $Id: delete.c,v 1.72 2004/06/03 16:08:41 danielk1977 Exp $
|
||||
** $Id: delete.c,v 1.73 2004/06/10 10:50:15 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -193,6 +193,13 @@ void sqlite3DeleteFrom(
|
||||
** the table and pick which records to delete.
|
||||
*/
|
||||
else{
|
||||
/* Ensure all required collation sequences are available. */
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
if( sqlite3CheckIndexCollSeq(pParse, pIdx) ){
|
||||
goto delete_from_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* Begin the database scan
|
||||
*/
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 1, 0);
|
||||
|
44
src/expr.c
44
src/expr.c
@@ -12,7 +12,7 @@
|
||||
** This file contains routines used for analyzing expressions and
|
||||
** for generating VDBE code that evaluates expressions in SQLite.
|
||||
**
|
||||
** $Id: expr.c,v 1.137 2004/06/09 09:55:18 danielk1977 Exp $
|
||||
** $Id: expr.c,v 1.138 2004/06/10 10:50:17 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@@ -59,14 +59,18 @@ char sqlite3ExprAffinity(Expr *pExpr){
|
||||
** Return the default collation sequence for the expression pExpr. If
|
||||
** there is no default collation type, return 0.
|
||||
*/
|
||||
CollSeq *sqlite3ExprCollSeq(Expr *pExpr){
|
||||
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
|
||||
CollSeq *pColl = 0;
|
||||
if( pExpr ){
|
||||
if( pExpr->pColl ) return pExpr->pColl;
|
||||
if( pExpr->op==TK_AS ){
|
||||
return sqlite3ExprCollSeq(pExpr->pLeft);
|
||||
pColl = pExpr->pColl;
|
||||
if( pExpr->op==TK_AS && !pColl ){
|
||||
return sqlite3ExprCollSeq(pParse, pExpr->pLeft);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
if( sqlite3CheckCollSeq(pParse, pColl) ){
|
||||
pColl = 0;
|
||||
}
|
||||
return pColl;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -157,10 +161,10 @@ static int binaryCompareP1(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
|
||||
** is used, or the default (BINARY) if neither expression has a collating
|
||||
** type.
|
||||
*/
|
||||
static CollSeq* binaryCompareCollSeq(Expr *pLeft, Expr *pRight){
|
||||
CollSeq *pColl = sqlite3ExprCollSeq(pLeft);
|
||||
static CollSeq* binaryCompareCollSeq(Parse *pParse, Expr *pLeft, Expr *pRight){
|
||||
CollSeq *pColl = sqlite3ExprCollSeq(pParse, pLeft);
|
||||
if( !pColl ){
|
||||
pColl = sqlite3ExprCollSeq(pRight);
|
||||
pColl = sqlite3ExprCollSeq(pParse, pRight);
|
||||
}
|
||||
return pColl;
|
||||
}
|
||||
@@ -868,7 +872,7 @@ int sqlite3ExprResolveIds(
|
||||
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
|
||||
sqlite3Select(pParse, pExpr->pSelect, SRT_Set, iParm, 0, 0, 0, 0);
|
||||
if( pExpr->pSelect->pEList && pExpr->pSelect->pEList->nExpr>0 ){
|
||||
keyInfo.aColl[0] = binaryCompareCollSeq(pExpr->pLeft,
|
||||
keyInfo.aColl[0] = binaryCompareCollSeq(pParse, pExpr->pLeft,
|
||||
pExpr->pSelect->pEList->a[0].pExpr);
|
||||
}
|
||||
}else if( pExpr->pList ){
|
||||
@@ -1195,7 +1199,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
|
||||
case TK_NE:
|
||||
case TK_EQ: {
|
||||
int p1 = binaryCompareP1(pExpr->pLeft, pExpr->pRight, 0);
|
||||
CollSeq *p3 = binaryCompareCollSeq(pExpr->pLeft, pExpr->pRight);
|
||||
CollSeq *p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
|
||||
sqlite3ExprCode(pParse, pExpr->pLeft);
|
||||
sqlite3ExprCode(pParse, pExpr->pRight);
|
||||
sqlite3VdbeOp3(v, op, p1, 0, (void *)p3, P3_COLLSEQ);
|
||||
@@ -1326,12 +1330,12 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
|
||||
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
|
||||
sqlite3ExprCode(pParse, pExpr->pList->a[0].pExpr);
|
||||
p1 = binaryCompareP1(pExpr->pLeft, pExpr->pList->a[0].pExpr, 0);
|
||||
p3 = binaryCompareCollSeq(pExpr->pLeft, pExpr->pList->a[0].pExpr);
|
||||
p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pList->a[0].pExpr);
|
||||
sqlite3VdbeOp3(v, OP_Ge, p1, 0, (void *)p3, P3_COLLSEQ);
|
||||
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
|
||||
sqlite3ExprCode(pParse, pExpr->pList->a[1].pExpr);
|
||||
p1 = binaryCompareP1(pExpr->pLeft, pExpr->pList->a[1].pExpr, 0);
|
||||
p3 = binaryCompareCollSeq(pExpr->pLeft, pExpr->pList->a[1].pExpr);
|
||||
p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pList->a[1].pExpr);
|
||||
sqlite3VdbeOp3(v, OP_Le, p1, 0, (void *)p3, P3_COLLSEQ);
|
||||
sqlite3VdbeAddOp(v, OP_And, 0, 0);
|
||||
break;
|
||||
@@ -1360,7 +1364,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
|
||||
sqlite3ExprCode(pParse, pExpr->pList->a[i].pExpr);
|
||||
if( pExpr->pLeft ){
|
||||
int p1 = binaryCompareP1(pExpr->pLeft, pExpr->pList->a[i].pExpr, 1);
|
||||
CollSeq *p3 = binaryCompareCollSeq(pExpr->pLeft,
|
||||
CollSeq *p3 = binaryCompareCollSeq(pParse, pExpr->pLeft,
|
||||
pExpr->pList->a[i].pExpr);
|
||||
sqlite3VdbeAddOp(v, OP_Dup, 1, 1);
|
||||
jumpInst = sqlite3VdbeOp3(v, OP_Ne, p1, 0, (void *)p3, P3_COLLSEQ);
|
||||
@@ -1476,7 +1480,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
case TK_NE:
|
||||
case TK_EQ: {
|
||||
int p1 = binaryCompareP1(pExpr->pLeft, pExpr->pRight, jumpIfNull);
|
||||
CollSeq *p3 = binaryCompareCollSeq(pExpr->pLeft, pExpr->pRight);
|
||||
CollSeq *p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
|
||||
sqlite3ExprCode(pParse, pExpr->pLeft);
|
||||
sqlite3ExprCode(pParse, pExpr->pRight);
|
||||
sqlite3VdbeOp3(v, op, p1, dest, (void *)p3, P3_COLLSEQ);
|
||||
@@ -1502,12 +1506,12 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
|
||||
sqlite3ExprCode(pParse, pExpr->pList->a[0].pExpr);
|
||||
p1 = binaryCompareP1(pExpr->pLeft, pExpr->pList->a[0].pExpr, !jumpIfNull);
|
||||
p3 = binaryCompareCollSeq(pExpr->pLeft, pExpr->pList->a[0].pExpr);
|
||||
p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pList->a[0].pExpr);
|
||||
addr = sqlite3VdbeOp3(v, OP_Lt, p1, 0, (void *)p3, P3_COLLSEQ);
|
||||
|
||||
sqlite3ExprCode(pParse, pExpr->pList->a[1].pExpr);
|
||||
p1 = binaryCompareP1(pExpr->pLeft, pExpr->pList->a[1].pExpr, jumpIfNull);
|
||||
p3 = binaryCompareCollSeq(pExpr->pLeft, pExpr->pList->a[1].pExpr);
|
||||
p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pList->a[1].pExpr);
|
||||
sqlite3VdbeOp3(v, OP_Le, p1, dest, (void *)p3, P3_COLLSEQ);
|
||||
|
||||
sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
|
||||
@@ -1570,7 +1574,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
case TK_NE:
|
||||
case TK_EQ: {
|
||||
int p1 = binaryCompareP1(pExpr->pLeft, pExpr->pRight, jumpIfNull);
|
||||
CollSeq *p3 = binaryCompareCollSeq(pExpr->pLeft, pExpr->pRight);
|
||||
CollSeq *p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
|
||||
sqlite3ExprCode(pParse, pExpr->pLeft);
|
||||
sqlite3ExprCode(pParse, pExpr->pRight);
|
||||
sqlite3VdbeOp3(v, op, p1, dest, (void *)p3, P3_COLLSEQ);
|
||||
@@ -1597,13 +1601,13 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
sqlite3ExprCode(pParse, pExpr->pList->a[0].pExpr);
|
||||
addr = sqlite3VdbeCurrentAddr(v);
|
||||
p1 = binaryCompareP1(pExpr->pLeft, pExpr->pList->a[0].pExpr, !jumpIfNull);
|
||||
p3 = binaryCompareCollSeq(pExpr->pLeft, pExpr->pList->a[0].pExpr);
|
||||
p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pList->a[0].pExpr);
|
||||
sqlite3VdbeOp3(v, OP_Ge, p1, addr+3, (void *)p3, P3_COLLSEQ);
|
||||
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Goto, 0, dest);
|
||||
sqlite3ExprCode(pParse, pExpr->pList->a[1].pExpr);
|
||||
p1 = binaryCompareP1(pExpr->pLeft, pExpr->pList->a[1].pExpr, jumpIfNull);
|
||||
p3 = binaryCompareCollSeq(pExpr->pLeft, pExpr->pList->a[1].pExpr);
|
||||
p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pList->a[1].pExpr);
|
||||
sqlite3VdbeOp3(v, OP_Gt, p1, dest, (void *)p3, P3_COLLSEQ);
|
||||
break;
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle INSERT statements in SQLite.
|
||||
**
|
||||
** $Id: insert.c,v 1.109 2004/05/31 08:55:34 danielk1977 Exp $
|
||||
** $Id: insert.c,v 1.110 2004/06/10 10:50:21 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -234,6 +234,13 @@ void sqlite3Insert(
|
||||
goto insert_cleanup;
|
||||
}
|
||||
|
||||
/* Ensure all required collation sequences are available. */
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
if( sqlite3CheckIndexCollSeq(pParse, pIdx) ){
|
||||
goto insert_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate a VDBE
|
||||
*/
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
|
24
src/main.c
24
src/main.c
@@ -14,7 +14,7 @@
|
||||
** other files are for internal use by SQLite and should not be
|
||||
** accessed by users of the library.
|
||||
**
|
||||
** $Id: main.c,v 1.213 2004/06/10 02:16:02 danielk1977 Exp $
|
||||
** $Id: main.c,v 1.214 2004/06/10 10:50:22 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@@ -1217,3 +1217,25 @@ int sqlite3_create_collation16(
|
||||
sqliteFree(zName8);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int sqlite3_collation_needed(
|
||||
sqlite3 *db,
|
||||
void *pCollNeededArg,
|
||||
void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*)
|
||||
){
|
||||
db->xCollNeeded = xCollNeeded;
|
||||
db->xCollNeeded16 = 0;
|
||||
db->pCollNeededArg = pCollNeededArg;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
int sqlite3_collation_needed16(
|
||||
sqlite3 *db,
|
||||
void *pCollNeededArg,
|
||||
void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*)
|
||||
){
|
||||
db->xCollNeeded = 0;
|
||||
db->xCollNeeded16 = xCollNeeded16;
|
||||
db->pCollNeededArg = pCollNeededArg;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** This file contains code used to implement the PRAGMA command.
|
||||
**
|
||||
** $Id: pragma.c,v 1.41 2004/06/10 01:30:59 drh Exp $
|
||||
** $Id: pragma.c,v 1.42 2004/06/10 10:50:25 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@@ -655,6 +655,7 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){
|
||||
sqlite3VdbeAddOp(v, OP_Integer, pTab->tnum, 0);
|
||||
cnt++;
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
if( sqlite3CheckIndexCollSeq(pParse, pIdx) ) return;
|
||||
sqlite3VdbeAddOp(v, OP_Integer, pIdx->tnum, 0);
|
||||
cnt++;
|
||||
}
|
||||
|
36
src/select.c
36
src/select.c
@@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle SELECT statements in SQLite.
|
||||
**
|
||||
** $Id: select.c,v 1.185 2004/06/09 09:55:18 danielk1977 Exp $
|
||||
** $Id: select.c,v 1.186 2004/06/10 10:50:25 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -550,7 +550,7 @@ static void generateSortTail(
|
||||
** is stored in pOrderBy->a[i].zName. Otherwise, use the default
|
||||
** collation type for the expression.
|
||||
*/
|
||||
pInfo->aColl[i] = sqlite3ExprCollSeq(pOrderBy->a[i].pExpr);
|
||||
pInfo->aColl[i] = sqlite3ExprCollSeq(pParse, pOrderBy->a[i].pExpr);
|
||||
if( !pInfo->aColl[i] ){
|
||||
pInfo->aColl[i] = db->pDfltColl;
|
||||
}
|
||||
@@ -825,7 +825,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
|
||||
if( zType ){
|
||||
pTab->aCol[i].affinity = sqlite3AffinityType(zType, strlen(zType));
|
||||
}
|
||||
pTab->aCol[i].pColl = sqlite3ExprCollSeq(p);
|
||||
pTab->aCol[i].pColl = sqlite3ExprCollSeq(pParse, p);
|
||||
if( !pTab->aCol[i].pColl ){
|
||||
pTab->aCol[i].pColl = pParse->db->pDfltColl;
|
||||
}
|
||||
@@ -2233,21 +2233,6 @@ int sqlite3Select(
|
||||
}
|
||||
}
|
||||
|
||||
/* If there is an ORDER BY clause, resolve any collation sequences
|
||||
** names that have been explicitly specified.
|
||||
*/
|
||||
if( pOrderBy ){
|
||||
for(i=0; i<pOrderBy->nExpr; i++){
|
||||
if( pOrderBy->a[i].zName ){
|
||||
pOrderBy->a[i].pExpr->pColl =
|
||||
sqlite3LocateCollSeq(pParse, pOrderBy->a[i].zName, -1);
|
||||
}
|
||||
}
|
||||
if( pParse->nErr ){
|
||||
goto select_end;
|
||||
}
|
||||
}
|
||||
|
||||
/* Begin generating code.
|
||||
*/
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
@@ -2323,6 +2308,21 @@ int sqlite3Select(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* If there is an ORDER BY clause, resolve any collation sequences
|
||||
** names that have been explicitly specified.
|
||||
*/
|
||||
if( pOrderBy ){
|
||||
for(i=0; i<pOrderBy->nExpr; i++){
|
||||
if( pOrderBy->a[i].zName ){
|
||||
pOrderBy->a[i].pExpr->pColl =
|
||||
sqlite3LocateCollSeq(pParse, pOrderBy->a[i].zName, -1);
|
||||
}
|
||||
}
|
||||
if( pParse->nErr ){
|
||||
goto select_end;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the limiter.
|
||||
*/
|
||||
computeLimitRegisters(pParse, p);
|
||||
|
@@ -12,7 +12,7 @@
|
||||
** This header file defines the interface that the SQLite library
|
||||
** presents to client programs.
|
||||
**
|
||||
** @(#) $Id: sqlite.h.in,v 1.96 2004/06/10 02:16:02 danielk1977 Exp $
|
||||
** @(#) $Id: sqlite.h.in,v 1.97 2004/06/10 10:50:30 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef _SQLITE_H_
|
||||
#define _SQLITE_H_
|
||||
@@ -967,21 +967,84 @@ void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
|
||||
#define SQLITE_UTF16LE 2
|
||||
#define SQLITE_UTF16BE 3
|
||||
|
||||
/*
|
||||
** These two functions are used to add new collation sequences to the
|
||||
** sqlite3 handle specified as the first argument.
|
||||
**
|
||||
** The name of the new collation sequence is specified as a UTF-8 string
|
||||
** for sqlite3_create_collation() and a UTF-16 string for
|
||||
** sqlite3_create_collation16(). In both cases the name is passed as the
|
||||
** second function argument.
|
||||
**
|
||||
** The third argument must be one of the constants SQLITE_UTF8,
|
||||
** SQLITE_UTF16LE or SQLITE_UTF16BE, indicating that the user-supplied
|
||||
** routine expects to be passed pointers to strings encoded using UTF-8,
|
||||
** UTF-16 little-endian or UTF-16 big-endian respectively.
|
||||
**
|
||||
** A pointer to the user supplied routine must be passed as the fifth
|
||||
** argument. If it is NULL, this is the same as deleting the collation
|
||||
** sequence (so that SQLite cannot call it anymore). Each time the user
|
||||
** supplied function is invoked, it is passed a copy of the void* passed as
|
||||
** the fourth argument to sqlite3_create_collation() or
|
||||
** sqlite3_create_collation16() as its first parameter.
|
||||
**
|
||||
** The remaining arguments to the user-supplied routine are two strings,
|
||||
** each represented by a [length, data] pair and encoded in the encoding
|
||||
** that was passed as the third argument when the collation sequence was
|
||||
** registered. The user routine should return negative, zero or positive if
|
||||
** the first string is less than, equal to, or greater than the second
|
||||
** string. i.e. (STRING1 - STRING2).
|
||||
*/
|
||||
int sqlite3_create_collation(
|
||||
sqlite3*,
|
||||
const char *zName,
|
||||
int enc,
|
||||
int eTextRep,
|
||||
void*,
|
||||
int(*xCompare)(void*,int,const void*,int,const void*)
|
||||
);
|
||||
int sqlite3_create_collation16(
|
||||
sqlite3*,
|
||||
const char *zName,
|
||||
int enc,
|
||||
int eTextRep,
|
||||
void*,
|
||||
int(*xCompare)(void*,int,const void*,int,const void*)
|
||||
);
|
||||
|
||||
/*
|
||||
** To avoid having to register all collation sequences before a database
|
||||
** can be used, a single callback function may be registered with the
|
||||
** database handle to be called whenever an undefined collation sequence is
|
||||
** required.
|
||||
**
|
||||
** If the function is registered using the sqlite3_collation_needed() API,
|
||||
** then it is passed the names of undefined collation sequences as strings
|
||||
** encoded in UTF-8. If sqlite3_collation_needed16() is used, the names
|
||||
** are passed as UTF-16 in machine native byte order. A call to either
|
||||
** function replaces any existing callback.
|
||||
**
|
||||
** When the user-function is invoked, the first argument passed is a copy
|
||||
** of the second argument to sqlite3_collation_needed() or
|
||||
** sqlite3_collation_needed16(). The second argument is the database
|
||||
** handle. The third argument is one of SQLITE_UTF8, SQLITE_UTF16BE or
|
||||
** SQLITE_UTF16LE, indicating the most desirable form of the collation
|
||||
** sequence function required. The fourth parameter is the name of the
|
||||
** required collation sequence.
|
||||
**
|
||||
** The collation sequence is returned to SQLite by a collation-needed
|
||||
** callback using the sqlite3_create_collation() or
|
||||
** sqlite3_create_collation16() APIs, described above.
|
||||
*/
|
||||
int sqlite3_collation_needed(
|
||||
sqlite3*,
|
||||
void*,
|
||||
void(*)(void*,sqlite3*,int eTextRep,const char*)
|
||||
);
|
||||
int sqlite3_collation_needed16(
|
||||
sqlite3*,
|
||||
void*,
|
||||
void(*)(void*,sqlite3*,int eTextRep,const void*)
|
||||
);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* End of the 'extern "C"' block */
|
||||
|
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.279 2004/06/10 02:16:02 danielk1977 Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.280 2004/06/10 10:50:32 danielk1977 Exp $
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "sqlite3.h"
|
||||
@@ -423,6 +423,9 @@ struct sqlite {
|
||||
u8 enc; /* Text encoding for this database. */
|
||||
u8 autoCommit; /* The auto-commit flag. */
|
||||
int nMaster; /* Length of master journal name. -1=unknown */
|
||||
void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*);
|
||||
void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
|
||||
void *pCollNeededArg;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1395,4 +1398,6 @@ int sqlite3ReadUniChar(const char *zStr, int *pOffset, u8 *pEnc, int fold);
|
||||
int sqlite3ReadSchema(sqlite *db, char **);
|
||||
CollSeq *sqlite3FindCollSeq(sqlite *,u8 enc, const char *,int,int);
|
||||
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName);
|
||||
CollSeq *sqlite3ExprCollSeq(Expr *pExpr);
|
||||
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
|
||||
int sqlite3CheckCollSeq(Parse *, CollSeq *);
|
||||
int sqlite3CheckIndexCollSeq(Parse *, Index *);
|
||||
|
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** A TCL Interface to SQLite
|
||||
**
|
||||
** $Id: tclsqlite.c,v 1.82 2004/06/10 02:16:02 danielk1977 Exp $
|
||||
** $Id: tclsqlite.c,v 1.83 2004/06/10 10:50:38 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
|
||||
|
||||
@@ -69,7 +69,8 @@ struct SqliteDb {
|
||||
SqlFunc *pFunc; /* List of SQL functions */
|
||||
SqlCollate *pCollate; /* List of SQL collation functions */
|
||||
int rc; /* Return code of most recent sqlite3_exec() */
|
||||
int nChange; /* Database changes for the most recent eval */
|
||||
int nChange; /* Database changes for the most recent eval */
|
||||
Tcl_Obj *pCollateNeeded; /* Collation needed script */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -217,6 +218,20 @@ static int DbCommitHandler(void *cd){
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tclCollateNeeded(
|
||||
void *pCtx,
|
||||
sqlite *db,
|
||||
int enc,
|
||||
const char *zName
|
||||
){
|
||||
SqliteDb *pDb = (SqliteDb *)pCtx;
|
||||
Tcl_Obj *pScript = Tcl_DuplicateObj(pDb->pCollateNeeded);
|
||||
Tcl_IncrRefCount(pScript);
|
||||
Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(zName, -1));
|
||||
Tcl_EvalObjEx(pDb->interp, pScript, 0);
|
||||
Tcl_DecrRefCount(pScript);
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine is called to evaluate an SQL collation function implemented
|
||||
** using TCL script.
|
||||
@@ -382,7 +397,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
"errorcode", "eval", "function",
|
||||
"last_insert_rowid", "last_statement_changes", "onecolumn",
|
||||
"progress", "rekey", "timeout",
|
||||
"trace", "collate",
|
||||
"trace", "collate", "collation_needed",
|
||||
0
|
||||
};
|
||||
enum DB_enum {
|
||||
@@ -391,7 +406,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
DB_ERRORCODE, DB_EVAL, DB_FUNCTION,
|
||||
DB_LAST_INSERT_ROWID, DB_LAST_STATEMENT_CHANGES, DB_ONECOLUMN,
|
||||
DB_PROGRESS, DB_REKEY, DB_TIMEOUT,
|
||||
DB_TRACE, DB_COLLATE
|
||||
DB_TRACE, DB_COLLATE, DB_COLLATION_NEEDED
|
||||
};
|
||||
|
||||
if( objc<2 ){
|
||||
@@ -924,6 +939,26 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** $db collate_needed SCRIPT
|
||||
**
|
||||
** Create a new SQL collation function called NAME. Whenever
|
||||
** that function is called, invoke SCRIPT to evaluate the function.
|
||||
*/
|
||||
case DB_COLLATION_NEEDED: {
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "SCRIPT");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( pDb->pCollateNeeded ){
|
||||
Tcl_DecrRefCount(pDb->pCollateNeeded);
|
||||
}
|
||||
pDb->pCollateNeeded = Tcl_DuplicateObj(objv[2]);
|
||||
Tcl_IncrRefCount(pDb->pCollateNeeded);
|
||||
sqlite3_collation_needed(pDb->db, pDb, tclCollateNeeded);
|
||||
break;
|
||||
}
|
||||
|
||||
} /* End of the SWITCH statement */
|
||||
return rc;
|
||||
}
|
||||
@@ -1051,6 +1086,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
Md5_Register(p->db);
|
||||
}
|
||||
#endif
|
||||
p->interp = interp;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
@@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle UPDATE statements.
|
||||
**
|
||||
** $Id: update.c,v 1.81 2004/05/29 11:24:50 danielk1977 Exp $
|
||||
** $Id: update.c,v 1.82 2004/06/10 10:50:45 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -179,6 +179,7 @@ void sqlite3Update(
|
||||
}
|
||||
}
|
||||
if( i<pIdx->nColumn ){
|
||||
if( sqlite3CheckIndexCollSeq(pParse, pIdx) ) goto update_cleanup;
|
||||
apIdx[nIdx++] = pIdx;
|
||||
aIdxUsed[j] = 1;
|
||||
}else{
|
||||
|
Reference in New Issue
Block a user