/ Check-in [edf069b9]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add the sqlite3_collation_needed() API and fix some error handling cases involving unknown collation sequences. (CVS 1562)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:edf069b9f4044ed2a80962c7722052bf1b80bf45
User & Date: danielk1977 2004-06-10 10:50:08
Context
2004-06-10
10:51
Add the sqlite3_collation_needed() API and fix some error handling cases involving unknown collation sequences. (CVS 1563) check-in: 518d82d3 user: danielk1977 tags: trunk
10:50
Add the sqlite3_collation_needed() API and fix some error handling cases involving unknown collation sequences. (CVS 1562) check-in: edf069b9 user: danielk1977 tags: trunk
05:59
Misc fixes for test cases failing due to the new locking model. (CVS 1561) check-in: 71e98d0d user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/build.c.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
880
881
882
883
884
885
886
887

888
889
890
891
892
893
894
...
917
918
919
920
921
922
923








































































































924
925
926
927
928
929
930
...
934
935
936
937
938
939
940

941
942
943
944
945
946
947
948

949
950
951
952
953
954
955


956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985


986
987
988
989
990
991
992
993
994
995
996

997
998
999
1000
1001
1002
1003
1004
1005
....
1939
1940
1941
1942
1943
1944
1945





1946
1947
1948
1949
1950
1951
1952
....
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.214 2004/06/10 02:16:02 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Check to see if the schema for the database needs
................................................................................
    if( pColl ){
      pColl[0].zName = (char*)&pColl[3];
      pColl[0].enc = TEXT_Utf8;
      pColl[1].zName = (char*)&pColl[3];
      pColl[1].enc = TEXT_Utf16le;
      pColl[2].zName = (char*)&pColl[3];
      pColl[2].enc = TEXT_Utf16be;
      memcpy(pColl[0].zName, zName, nName+1);

      sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl);
    }
  }
  return pColl;
}

/*
................................................................................
      pColl = &pColl[1];
      break;
    default: 
      assert(!"Cannot happen");
  }
  return pColl;
}









































































































/*
** This function returns the collation sequence for database native text
** encoding identified by the string zName, length nName.
**
** If the requested collation sequence is not available, or not available
** in the database native encoding, the collation factory is invoked to
................................................................................
**
** If no versions of the requested collations sequence are available, or
** another error occurs, NULL is returned and an error message written into
** pParse.
*/
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 ){
    /* 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.  */

    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.


      */
      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 nothing has been found, write the error message into pParse */
  if( !pColl || !pColl->xCmp ){
    if( pParse->nErr==0 ){
      sqlite3SetNString(&pParse->zErrMsg, "no such collation sequence: ", -1,
          zName, nName, 0);
    }
    pParse->nErr++;

  }

  return pColl;
}



/*
** Scan the column type name zType (length nType) and return the
................................................................................
    if( pList->a[i].pExpr ){
      assert( pList->a[i].pExpr->pColl );
      pIndex->keyInfo.aColl[i] = pList->a[i].pExpr->pColl;
    }else{
      pIndex->keyInfo.aColl[i] = pTab->aCol[j].pColl;
    }
    assert( pIndex->keyInfo.aColl[i] );





  }
  pIndex->keyInfo.nField = pList->nExpr;

  /* Link the new Index structure to its table and to the other
  ** in-memory database structures. 
  */
  if( !pParse->explain ){
................................................................................
**
** Only database iDb and the temp database are made writable by this call.
** If iDb==0, then the main and temp databases are made writable.   If
** iDb==1 then only the temp database is made writable.  If iDb>1 then the
** 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);
  pParse->writeMask |= 1<<iDb;
  if( setStatement ){
    sqlite3VdbeAddOp(v, OP_Statement, iDb, 0);
  }







|







 







|
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
|
|



<
<
<
>

<

<
<
<
<
>
>

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
>





|





>

<







 







>
>
>
>
>







 







<







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
...
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
....
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051



1052
1053

1054




1055
1056
1057





























1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072

1073
1074
1075
1076
1077
1078
1079
....
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
....
2523
2524
2525
2526
2527
2528
2529

2530
2531
2532
2533
2534
2535
2536
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.215 2004/06/10 10:50:08 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Check to see if the schema for the database needs
................................................................................
    if( pColl ){
      pColl[0].zName = (char*)&pColl[3];
      pColl[0].enc = TEXT_Utf8;
      pColl[1].zName = (char*)&pColl[3];
      pColl[1].enc = TEXT_Utf16le;
      pColl[2].zName = (char*)&pColl[3];
      pColl[2].enc = TEXT_Utf16be;
      memcpy(pColl[0].zName, zName, nName);
      pColl[0].zName[nName] = 0;
      sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl);
    }
  }
  return pColl;
}

/*
................................................................................
      pColl = &pColl[1];
      break;
    default: 
      assert(!"Cannot happen");
  }
  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.
**
** If the requested collation sequence is not available, or not available
** in the database native encoding, the collation factory is invoked to
................................................................................
**
** If no versions of the requested collations sequence are available, or
** another error occurs, NULL is returned and an error message written into
** pParse.
*/
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){
  u8 enc = pParse->db->enc;
  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.
    */



    callCollNeeded(pParse->db, zName, nName);
    pColl = sqlite3FindCollSeq(pParse->db, enc, zName, nName, 0);

    if( pColl && !pColl->xCmp ){




      /* There may be a version of the collation sequence that requires
      ** translation between encodings. Search for it with synthCollSeq().
      */





























      if( synthCollSeq(pParse, pColl) ){
        return 0;
      }
    }
  }

  /* If nothing has been found, write the error message into pParse */
  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;
}



/*
** Scan the column type name zType (length nType) and return the
................................................................................
    if( pList->a[i].pExpr ){
      assert( pList->a[i].pExpr->pColl );
      pIndex->keyInfo.aColl[i] = pList->a[i].pExpr->pColl;
    }else{
      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;

  /* Link the new Index structure to its table and to the other
  ** in-memory database structures. 
  */
  if( !pParse->explain ){
................................................................................
**
** Only database iDb and the temp database are made writable by this call.
** If iDb==0, then the main and temp databases are made writable.   If
** iDb==1 then only the temp database is made writable.  If iDb>1 then the
** specified auxiliary database and the temp database are made writable.
*/
void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){

  Vdbe *v = sqlite3GetVdbe(pParse);
  if( v==0 ) return;
  sqlite3CodeVerifySchema(pParse, iDb);
  pParse->writeMask |= 1<<iDb;
  if( setStatement ){
    sqlite3VdbeAddOp(v, OP_Statement, iDb, 0);
  }

Changes to src/delete.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
189
190
191
192
193
194
195







196
197
198
199
200
201
202
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** 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 $
*/
#include "sqliteInt.h"

/*
** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.
................................................................................
    }
  }

  /* The usual case: There is a WHERE clause so we have to scan through
  ** the table and pick which records to delete.
  */
  else{







    /* Begin the database scan
    */
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 1, 0);
    if( pWInfo==0 ) goto delete_from_cleanup;

    /* Remember the key of every item to be deleted.
    */







|







 







>
>
>
>
>
>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.73 2004/06/10 10:50:15 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.
................................................................................
    }
  }

  /* The usual case: There is a WHERE clause so we have to scan through
  ** 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);
    if( pWInfo==0 ) goto delete_from_cleanup;

    /* Remember the key of every item to be deleted.
    */

Changes to src/expr.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
55
56
57
58
59
60
61
62

63
64
65
66
67
68



69
70
71
72
73
74
75
76
...
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
...
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
....
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
....
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
....
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
....
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
....
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
....
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
....
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** 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 $
*/
#include "sqliteInt.h"
#include <ctype.h>

char const *sqlite3AffinityString(char affinity){
  switch( affinity ){
    case SQLITE_AFF_INTEGER: return "i";
................................................................................
  return pExpr->affinity;
}

/*
** Return the default collation sequence for the expression pExpr. If
** there is no default collation type, return 0.
*/
CollSeq *sqlite3ExprCollSeq(Expr *pExpr){

  if( pExpr ){
    if( pExpr->pColl ) return pExpr->pColl;
    if( pExpr->op==TK_AS ){
      return sqlite3ExprCollSeq(pExpr->pLeft);
    }
  }



  return 0;
}

/*
** pExpr is the left operand of a comparison operator.  aff2 is the
** type affinity of the right operand.  This routine returns the
** type affinity that should be used for the comparison operator.
*/
................................................................................
** a binary comparison operator comparing pLeft and pRight.
**
** If the left hand expression has a collating sequence type, then it is
** used. Otherwise the collation sequence for the right hand expression
** is used, or the default (BINARY) if neither expression has a collating
** type.
*/
static CollSeq* binaryCompareCollSeq(Expr *pLeft, Expr *pRight){
  CollSeq *pColl = sqlite3ExprCollSeq(pLeft);
  if( !pColl ){
    pColl = sqlite3ExprCollSeq(pRight);
  }
  return pColl;
}

/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqliteMalloc().  The calling function
................................................................................
        ** Generate code to write the results of the select into the temporary
        ** table allocated and opened above.
        */
        int iParm = pExpr->iTable +  (((int)affinity)<<16);
        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,
              pExpr->pSelect->pEList->a[0].pExpr);
        }
      }else if( pExpr->pList ){
        /* Case 2:     expr IN (exprlist)
        **
	** For each expression, build an index key from the evaluation and
        ** store it in the temporary table. If <expr> is a column, then use
................................................................................
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      int p1 = binaryCompareP1(pExpr->pLeft, pExpr->pRight, 0);
      CollSeq *p3 = binaryCompareCollSeq(pExpr->pLeft, pExpr->pRight);
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3ExprCode(pParse, pExpr->pRight);
      sqlite3VdbeOp3(v, op, p1, 0, (void *)p3, P3_COLLSEQ);
      break;
    }
    case TK_AND:
    case TK_OR:
................................................................................
    case TK_BETWEEN: {
      int p1;
      CollSeq *p3;
      sqlite3ExprCode(pParse, pExpr->pLeft);
      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);
      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);
      sqlite3VdbeOp3(v, OP_Le, p1, 0, (void *)p3, P3_COLLSEQ);
      sqlite3VdbeAddOp(v, OP_And, 0, 0);
      break;
    }
    case TK_UPLUS:
    case TK_AS: {
      sqlite3ExprCode(pParse, pExpr->pLeft);
................................................................................
      if( pExpr->pLeft ){
        sqlite3ExprCode(pParse, pExpr->pLeft);
      }
      for(i=0; i<nExpr; i=i+2){
        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, 
              pExpr->pList->a[i].pExpr);
          sqlite3VdbeAddOp(v, OP_Dup, 1, 1);
          jumpInst = sqlite3VdbeOp3(v, OP_Ne, p1, 0, (void *)p3, P3_COLLSEQ);
          sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
        }else{
          jumpInst = sqlite3VdbeAddOp(v, OP_IfNot, 1, 0);
        }
................................................................................
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      int p1 = binaryCompareP1(pExpr->pLeft, pExpr->pRight, jumpIfNull);
      CollSeq *p3 = binaryCompareCollSeq(pExpr->pLeft, pExpr->pRight);
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3ExprCode(pParse, pExpr->pRight);
      sqlite3VdbeOp3(v, op, p1, dest, (void *)p3, P3_COLLSEQ);
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
................................................................................
      int addr;
      int p1;
      CollSeq *p3;
      sqlite3ExprCode(pParse, pExpr->pLeft);
      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);
      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);
      sqlite3VdbeOp3(v, OP_Le, p1, dest, (void *)p3, P3_COLLSEQ);

      sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
      sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
      sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
      break;
    }
................................................................................
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      int p1 = binaryCompareP1(pExpr->pLeft, pExpr->pRight, jumpIfNull);
      CollSeq *p3 = binaryCompareCollSeq(pExpr->pLeft, pExpr->pRight);
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3ExprCode(pParse, pExpr->pRight);
      sqlite3VdbeOp3(v, op, p1, dest, (void *)p3, P3_COLLSEQ);
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
................................................................................
      int p1;
      CollSeq *p3;
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
      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);
      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);
      sqlite3VdbeOp3(v, OP_Gt, p1, dest, (void *)p3, P3_COLLSEQ);
      break;
    }
    default: {
      sqlite3ExprCode(pParse, pExpr);
      sqlite3VdbeAddOp(v, OP_IfNot, jumpIfNull, dest);
      break;







|







 







|
>

|
|
|


>
>
>
|







 







|
|

|







 







|







 







|







 







|




|







 







|







 







|







 







|




|







 







|







 







|





|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
...
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
...
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
....
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
....
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
....
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
....
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
....
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
....
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
....
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.138 2004/06/10 10:50:17 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

char const *sqlite3AffinityString(char affinity){
  switch( affinity ){
    case SQLITE_AFF_INTEGER: return "i";
................................................................................
  return pExpr->affinity;
}

/*
** Return the default collation sequence for the expression pExpr. If
** there is no default collation type, return 0.
*/
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
  CollSeq *pColl = 0;
  if( pExpr ){
    pColl = pExpr->pColl;
    if( pExpr->op==TK_AS && !pColl ){
      return sqlite3ExprCollSeq(pParse, pExpr->pLeft);
    }
  }
  if( sqlite3CheckCollSeq(pParse, pColl) ){ 
    pColl = 0;
  }
  return pColl;
}

/*
** pExpr is the left operand of a comparison operator.  aff2 is the
** type affinity of the right operand.  This routine returns the
** type affinity that should be used for the comparison operator.
*/
................................................................................
** a binary comparison operator comparing pLeft and pRight.
**
** If the left hand expression has a collating sequence type, then it is
** used. Otherwise the collation sequence for the right hand expression
** is used, or the default (BINARY) if neither expression has a collating
** type.
*/
static CollSeq* binaryCompareCollSeq(Parse *pParse, Expr *pLeft, Expr *pRight){
  CollSeq *pColl = sqlite3ExprCollSeq(pParse, pLeft);
  if( !pColl ){
    pColl = sqlite3ExprCollSeq(pParse, pRight);
  }
  return pColl;
}

/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqliteMalloc().  The calling function
................................................................................
        ** Generate code to write the results of the select into the temporary
        ** table allocated and opened above.
        */
        int iParm = pExpr->iTable +  (((int)affinity)<<16);
        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(pParse, pExpr->pLeft,
              pExpr->pSelect->pEList->a[0].pExpr);
        }
      }else if( pExpr->pList ){
        /* Case 2:     expr IN (exprlist)
        **
	** For each expression, build an index key from the evaluation and
        ** store it in the temporary table. If <expr> is a column, then use
................................................................................
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      int p1 = binaryCompareP1(pExpr->pLeft, pExpr->pRight, 0);
      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);
      break;
    }
    case TK_AND:
    case TK_OR:
................................................................................
    case TK_BETWEEN: {
      int p1;
      CollSeq *p3;
      sqlite3ExprCode(pParse, pExpr->pLeft);
      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(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(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;
    }
    case TK_UPLUS:
    case TK_AS: {
      sqlite3ExprCode(pParse, pExpr->pLeft);
................................................................................
      if( pExpr->pLeft ){
        sqlite3ExprCode(pParse, pExpr->pLeft);
      }
      for(i=0; i<nExpr; i=i+2){
        sqlite3ExprCode(pParse, pExpr->pList->a[i].pExpr);
        if( pExpr->pLeft ){
          int p1 = binaryCompareP1(pExpr->pLeft, pExpr->pList->a[i].pExpr, 1);
          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);
          sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
        }else{
          jumpInst = sqlite3VdbeAddOp(v, OP_IfNot, 1, 0);
        }
................................................................................
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      int p1 = binaryCompareP1(pExpr->pLeft, pExpr->pRight, jumpIfNull);
      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);
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
................................................................................
      int addr;
      int p1;
      CollSeq *p3;
      sqlite3ExprCode(pParse, pExpr->pLeft);
      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(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(pParse, pExpr->pLeft, pExpr->pList->a[1].pExpr);
      sqlite3VdbeOp3(v, OP_Le, p1, dest, (void *)p3, P3_COLLSEQ);

      sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
      sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
      sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
      break;
    }
................................................................................
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      int p1 = binaryCompareP1(pExpr->pLeft, pExpr->pRight, jumpIfNull);
      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);
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
................................................................................
      int p1;
      CollSeq *p3;
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
      sqlite3ExprCode(pParse, pExpr->pList->a[0].pExpr);
      addr = sqlite3VdbeCurrentAddr(v);
      p1 = binaryCompareP1(pExpr->pLeft, pExpr->pList->a[0].pExpr, !jumpIfNull);
      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(pParse, pExpr->pLeft, pExpr->pList->a[1].pExpr);
      sqlite3VdbeOp3(v, OP_Gt, p1, dest, (void *)p3, P3_COLLSEQ);
      break;
    }
    default: {
      sqlite3ExprCode(pParse, pExpr);
      sqlite3VdbeAddOp(v, OP_IfNot, jumpIfNull, dest);
      break;

Changes to src/insert.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
229
230
231
232
233
234
235







236
237
238
239
240
241
242
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** 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 $
*/
#include "sqliteInt.h"

/*
** Set P3 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
................................................................................
  if( pTab==0 ) goto insert_cleanup;

  /* If pTab is really a view, make sure it has been initialized.
  */
  if( isView && sqlite3ViewGetColumnNames(pParse, pTab) ){
    goto insert_cleanup;
  }








  /* Allocate a VDBE
  */
  v = sqlite3GetVdbe(pParse);
  if( v==0 ) goto insert_cleanup;
  sqlite3BeginWriteOperation(pParse, pSelect || row_triggers_exist, pTab->iDb);








|







 







>
>
>
>
>
>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.110 2004/06/10 10:50:21 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Set P3 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
................................................................................
  if( pTab==0 ) goto insert_cleanup;

  /* If pTab is really a view, make sure it has been initialized.
  */
  if( isView && sqlite3ViewGetColumnNames(pParse, pTab) ){
    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);
  if( v==0 ) goto insert_cleanup;
  sqlite3BeginWriteOperation(pParse, pSelect || row_triggers_exist, pTab->iDb);

Changes to src/main.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
....
1213
1214
1215
1216
1217
1218
1219






















**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** 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 $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** A pointer to this structure is used to communicate information
................................................................................
){
  int rc;
  char *zName8 = sqlite3utf16to8(zName, -1, SQLITE_BIGENDIAN);
  rc = sqlite3_create_collation(db, zName8, enc, pCtx, xCompare);
  sqliteFree(zName8);
  return rc;
}





























|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
....
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.214 2004/06/10 10:50:22 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** A pointer to this structure is used to communicate information
................................................................................
){
  int rc;
  char *zName8 = sqlite3utf16to8(zName, -1, SQLITE_BIGENDIAN);
  rc = sqlite3_create_collation(db, zName8, enc, pCtx, xCompare);
  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;
}

Changes to src/pragma.c.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
651
652
653
654
655
656
657

658
659
660
661
662
663
664
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.41 2004/06/10 01:30:59 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

#ifdef SQLITE_DEBUG
# include "pager.h"
# include "btree.h"
................................................................................
      */
      for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){
        Table *pTab = sqliteHashData(x);
        Index *pIdx;
        sqlite3VdbeAddOp(v, OP_Integer, pTab->tnum, 0);
        cnt++;
        for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){

          sqlite3VdbeAddOp(v, OP_Integer, pIdx->tnum, 0);
          cnt++;
        }
      }
      sqlite3VdbeAddOp(v, OP_IntegrityCk, cnt, i);
      sqlite3VdbeAddOp(v, OP_Dup, 0, 1);
      addr = sqlite3VdbeOp3(v, OP_String8, 0, 0, "ok", P3_STATIC);







|







 







>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.42 2004/06/10 10:50:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

#ifdef SQLITE_DEBUG
# include "pager.h"
# include "btree.h"
................................................................................
      */
      for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){
        Table *pTab = sqliteHashData(x);
        Index *pIdx;
        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++;
        }
      }
      sqlite3VdbeAddOp(v, OP_IntegrityCk, cnt, i);
      sqlite3VdbeAddOp(v, OP_Dup, 0, 1);
      addr = sqlite3VdbeOp3(v, OP_String8, 0, 0, "ok", P3_STATIC);

Changes to src/select.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
...
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
....
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
....
2318
2319
2320
2321
2322
2323
2324















2325
2326
2327
2328
2329
2330
2331
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** 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 $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
................................................................................
  pInfo->aSortOrder = (char*)&pInfo->aColl[nCol];
  pInfo->nField = nCol;
  for(i=0; i<nCol; i++){
    /* If a collation sequence was specified explicity, then it
    ** is stored in pOrderBy->a[i].zName. Otherwise, use the default
    ** collation type for the expression.
    */
    pInfo->aColl[i] = sqlite3ExprCollSeq(pOrderBy->a[i].pExpr);
    if( !pInfo->aColl[i] ){
      pInfo->aColl[i] = db->pDfltColl;
    }
    pInfo->aSortOrder[i] = pOrderBy->a[i].sortOrder;
  }
  sqlite3VdbeOp3(v, OP_Sort, 0, 0, (char*)pInfo, P3_KEYINFO_HANDOFF);
  addr = sqlite3VdbeAddOp(v, OP_SortNext, 0, end1);
................................................................................

    zType = sqliteStrDup(columnType(pParse, pSelect->pSrc ,p));
    pTab->aCol[i].zType = zType;
    pTab->aCol[i].affinity = SQLITE_AFF_NUMERIC;
    if( zType ){
      pTab->aCol[i].affinity = sqlite3AffinityType(zType, strlen(zType));
    }
    pTab->aCol[i].pColl = sqlite3ExprCollSeq(p);
    if( !pTab->aCol[i].pColl ){
      pTab->aCol[i].pColl = pParse->db->pDfltColl;
    }
  }
  pTab->iPKey = -1;
  return pTab;
}
................................................................................
             "between 1 and %d", iCol, pEList->nExpr);
          goto select_end;
        }
      }
    }
  }

  /* 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);
  if( v==0 ) goto select_end;

  /* Identify column names if we will be using them in a callback.  This
  ** step is skipped if the output is going to some other destination.
................................................................................
  ** If flattening is a possiblity, do so and return immediately.  
  */
  if( pParent && pParentAgg &&
      flattenSubquery(pParse, pParent, parentTab, *pParentAgg, isAgg) ){
    if( isAgg ) *pParentAgg = 1;
    return rc;
  }
















  /* Set the limiter.
  */
  computeLimitRegisters(pParse, p);

  /* If the output is destined for a temporary table, open that table.
  */







|







 







|







 







|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
...
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
....
2229
2230
2231
2232
2233
2234
2235















2236
2237
2238
2239
2240
2241
2242
....
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.186 2004/06/10 10:50:25 danielk1977 Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
................................................................................
  pInfo->aSortOrder = (char*)&pInfo->aColl[nCol];
  pInfo->nField = nCol;
  for(i=0; i<nCol; i++){
    /* If a collation sequence was specified explicity, then it
    ** is stored in pOrderBy->a[i].zName. Otherwise, use the default
    ** collation type for the expression.
    */
    pInfo->aColl[i] = sqlite3ExprCollSeq(pParse, pOrderBy->a[i].pExpr);
    if( !pInfo->aColl[i] ){
      pInfo->aColl[i] = db->pDfltColl;
    }
    pInfo->aSortOrder[i] = pOrderBy->a[i].sortOrder;
  }
  sqlite3VdbeOp3(v, OP_Sort, 0, 0, (char*)pInfo, P3_KEYINFO_HANDOFF);
  addr = sqlite3VdbeAddOp(v, OP_SortNext, 0, end1);
................................................................................

    zType = sqliteStrDup(columnType(pParse, pSelect->pSrc ,p));
    pTab->aCol[i].zType = zType;
    pTab->aCol[i].affinity = SQLITE_AFF_NUMERIC;
    if( zType ){
      pTab->aCol[i].affinity = sqlite3AffinityType(zType, strlen(zType));
    }
    pTab->aCol[i].pColl = sqlite3ExprCollSeq(pParse, p);
    if( !pTab->aCol[i].pColl ){
      pTab->aCol[i].pColl = pParse->db->pDfltColl;
    }
  }
  pTab->iPKey = -1;
  return pTab;
}
................................................................................
             "between 1 and %d", iCol, pEList->nExpr);
          goto select_end;
        }
      }
    }
  }
















  /* Begin generating code.
  */
  v = sqlite3GetVdbe(pParse);
  if( v==0 ) goto select_end;

  /* Identify column names if we will be using them in a callback.  This
  ** step is skipped if the output is going to some other destination.
................................................................................
  ** If flattening is a possiblity, do so and return immediately.  
  */
  if( pParent && pParentAgg &&
      flattenSubquery(pParse, pParent, parentTab, *pParentAgg, isAgg) ){
    if( isAgg ) *pParentAgg = 1;
    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);

  /* If the output is destined for a temporary table, open that table.
  */

Changes to src/sqlite.h.in.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
963
964
965
966
967
968
969




























970
971
972
973
974
975
976
977
978
979
980
981
982
983



































984
985
986
987
988
989
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** 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 $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
void sqlite3_result_text16(sqlite3_context*, const void*, int n, int eCopy);
void sqlite3_result_value(sqlite3_context*, sqlite3_value*);

#define SQLITE_UTF8    1
#define SQLITE_UTF16LE 2
#define SQLITE_UTF16BE 3





























int sqlite3_create_collation(
  sqlite3*, 
  const char *zName, 
  int enc, 
  void*,
  int(*xCompare)(void*,int,const void*,int,const void*)
);
int sqlite3_create_collation16(
  sqlite3*, 
  const char *zName, 
  int enc, 
  void*,
  int(*xCompare)(void*,int,const void*,int,const void*)
);





































#ifdef __cplusplus
}  /* End of the 'extern "C"' block */
#endif
#endif







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|






|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.97 2004/06/10 10:50:30 danielk1977 Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
void sqlite3_result_text16(sqlite3_context*, const void*, int n, int eCopy);
void sqlite3_result_value(sqlite3_context*, sqlite3_value*);

#define SQLITE_UTF8    1
#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 eTextRep, 
  void*,
  int(*xCompare)(void*,int,const void*,int,const void*)
);
int sqlite3_create_collation16(
  sqlite3*, 
  const char *zName, 
  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 */
#endif
#endif

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
419
420
421
422
423
424
425



426
427
428
429
430
431
432
....
1391
1392
1393
1394
1395
1396
1397
1398


**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.279 2004/06/10 02:16:02 danielk1977 Exp $
*/
#include "config.h"
#include "sqlite3.h"
#include "hash.h"
#include "parse.h"
#include <stdio.h>
#include <stdlib.h>
................................................................................

  int errCode;                  /* Most recent error code (SQLITE_*) */
  char *zErrMsg;                /* Most recent error message (UTF-8 encoded) */
  void *zErrMsg16;              /* Most recent error message (UTF-16 encoded) */
  u8 enc;                       /* Text encoding for this database. */
  u8 autoCommit;                /* The auto-commit flag. */
  int nMaster;                  /* Length of master journal name. -1=unknown */



};

/*
** Possible values for the sqlite.flags and or Db.flags fields.
**
** On sqlite.flags, the SQLITE_InTrans value means that we have
** executed a BEGIN.  On Db.flags, SQLITE_InTrans means a statement
................................................................................
void *sqlite3HexToBlob(const char *z);
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
const char *sqlite3ErrStr(int);
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);









|







 







>
>
>







 







|
>
>
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
....
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.280 2004/06/10 10:50:32 danielk1977 Exp $
*/
#include "config.h"
#include "sqlite3.h"
#include "hash.h"
#include "parse.h"
#include <stdio.h>
#include <stdlib.h>
................................................................................

  int errCode;                  /* Most recent error code (SQLITE_*) */
  char *zErrMsg;                /* Most recent error message (UTF-8 encoded) */
  void *zErrMsg16;              /* Most recent error message (UTF-16 encoded) */
  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;
};

/*
** Possible values for the sqlite.flags and or Db.flags fields.
**
** On sqlite.flags, the SQLITE_InTrans value means that we have
** executed a BEGIN.  On Db.flags, SQLITE_InTrans means a statement
................................................................................
void *sqlite3HexToBlob(const char *z);
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
const char *sqlite3ErrStr(int);
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(Parse *pParse, Expr *pExpr);
int sqlite3CheckCollSeq(Parse *, CollSeq *);
int sqlite3CheckIndexCollSeq(Parse *, Index *);

Changes to src/tclsqlite.c.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
65
66
67
68
69
70
71
72

73
74
75
76
77
78
79
...
212
213
214
215
216
217
218














219
220
221
222
223
224
225
...
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
...
919
920
921
922
923
924
925




















926
927
928
929
930
931
932
....
1047
1048
1049
1050
1051
1052
1053

1054
1055
1056
1057
1058
1059
1060
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.82 2004/06/10 02:16:02 danielk1977 Exp $
*/
#ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */

#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
................................................................................
  char *zCommit;        /* The commit hook callback routine */
  char *zTrace;         /* The trace callback routine */
  char *zProgress;      /* The progress callback routine */
  char *zAuth;          /* The authorization callback routine */
  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 */

};

/*
** An instance of this structure passes information thru the sqlite
** logic from the original TCL command into the callback routine.
*/
typedef struct CallbackData CallbackData;
................................................................................

  rc = Tcl_Eval(pDb->interp, pDb->zCommit);
  if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
    return 1;
  }
  return 0;
}















/*
** This routine is called to evaluate an SQL collation function implemented
** using TCL script.
*/
static int tclSqlCollate(
  void *pCtx,
................................................................................
  int rc = TCL_OK;
  static const char *DB_strs[] = {
    "authorizer",         "busy",                   "changes",
    "close",              "commit_hook",            "complete",
    "errorcode",          "eval",                   "function",
    "last_insert_rowid",  "last_statement_changes", "onecolumn",
    "progress",           "rekey",                  "timeout",
    "trace",              "collate",
    0                    
  };
  enum DB_enum {
    DB_AUTHORIZER,        DB_BUSY,                   DB_CHANGES,
    DB_CLOSE,             DB_COMMIT_HOOK,            DB_COMPLETE,
    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
  };

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
    return TCL_ERROR;
  }
  if( Tcl_GetIndexFromObj(interp, objv[1], DB_strs, "option", 0, &choice) ){
................................................................................
    strcpy(pCollate->zScript, zScript);
    if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8, 
        pCollate, tclSqlCollate) ){
      return TCL_ERROR;
    }
    break;
  }





















  } /* End of the SWITCH statement */
  return rc;
}

/*
**   sqlite DBNAME FILENAME ?MODE? ?-key KEY?
................................................................................
  */
#ifdef SQLITE_TEST
  {
    extern void Md5_Register(sqlite*);
    Md5_Register(p->db);
   }
#endif  

  return TCL_OK;
}

/*
** Provide a dummy Tcl_InitStubs if we are using this as a static
** library.
*/







|







 







|
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|








|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
...
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
...
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
...
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
....
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** A TCL Interface to SQLite
**
** $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 */

#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
................................................................................
  char *zCommit;        /* The commit hook callback routine */
  char *zTrace;         /* The trace callback routine */
  char *zProgress;      /* The progress callback routine */
  char *zAuth;          /* The authorization callback routine */
  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 */
  Tcl_Obj *pCollateNeeded;  /* Collation needed script */
};

/*
** An instance of this structure passes information thru the sqlite
** logic from the original TCL command into the callback routine.
*/
typedef struct CallbackData CallbackData;
................................................................................

  rc = Tcl_Eval(pDb->interp, pDb->zCommit);
  if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
    return 1;
  }
  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.
*/
static int tclSqlCollate(
  void *pCtx,
................................................................................
  int rc = TCL_OK;
  static const char *DB_strs[] = {
    "authorizer",         "busy",                   "changes",
    "close",              "commit_hook",            "complete",
    "errorcode",          "eval",                   "function",
    "last_insert_rowid",  "last_statement_changes", "onecolumn",
    "progress",           "rekey",                  "timeout",
    "trace",              "collate",                "collation_needed",
    0                    
  };
  enum DB_enum {
    DB_AUTHORIZER,        DB_BUSY,                   DB_CHANGES,
    DB_CLOSE,             DB_COMMIT_HOOK,            DB_COMPLETE,
    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_COLLATION_NEEDED
  };

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
    return TCL_ERROR;
  }
  if( Tcl_GetIndexFromObj(interp, objv[1], DB_strs, "option", 0, &choice) ){
................................................................................
    strcpy(pCollate->zScript, zScript);
    if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8, 
        pCollate, tclSqlCollate) ){
      return TCL_ERROR;
    }
    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;
}

/*
**   sqlite DBNAME FILENAME ?MODE? ?-key KEY?
................................................................................
  */
#ifdef SQLITE_TEST
  {
    extern void Md5_Register(sqlite*);
    Md5_Register(p->db);
   }
#endif  
  p->interp = interp;
  return TCL_OK;
}

/*
** Provide a dummy Tcl_InitStubs if we are using this as a static
** library.
*/

Changes to src/update.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
175
176
177
178
179
180
181

182
183
184
185
186
187
188
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** 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 $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
**
**   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
................................................................................
      i = 0;
    }else{
      for(i=0; i<pIdx->nColumn; i++){
        if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
      }
    }
    if( i<pIdx->nColumn ){

      apIdx[nIdx++] = pIdx;
      aIdxUsed[j] = 1;
    }else{
      aIdxUsed[j] = 0;
    }
  }








|







 







>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.82 2004/06/10 10:50:45 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
**
**   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
................................................................................
      i = 0;
    }else{
      for(i=0; i<pIdx->nColumn; i++){
        if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
      }
    }
    if( i<pIdx->nColumn ){
      if( sqlite3CheckIndexCollSeq(pParse, pIdx) ) goto update_cleanup;
      apIdx[nIdx++] = pIdx;
      aIdxUsed[j] = 1;
    }else{
      aIdxUsed[j] = 0;
    }
  }