SQLite4
Check-in [7d8efac62f]
Not logged in

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

Overview
SHA1 Hash:7d8efac62fe969b1f4ed8aba9c6e0510a0185c58
Date: 2013-06-17 20:15:50
User: dan
Comment:Modifications to make the ANALYZE command work (sqlite_stat1 only).
Tags And Properties
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to main.mk

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#OPTS += -DSQLITE4_DEBUG=1 -DLSM_DEBUG=1
OPTS += -DHAVE_GMTIME_R
OPTS += -DHAVE_LOCALTIME_R
OPTS += -DHAVE_MALLOC_USABLE_SIZE
OPTS += -DHAVE_USLEEP
#OPTS += -DSQLITE4_MEMDEBUG=1
#OPTS += -DSQLITE4_NO_SYNC=1 -DLSM_NO_SYNC=1
OPTS += -DSQLITE4_OMIT_ANALYZE
OPTS += -DSQLITE4_OMIT_AUTOMATIC_INDEX
OPTS += -DSQLITE4_OMIT_BTREECOUNT
OPTS += -DSQLITE4_OMIT_VIRTUALTABLE=1
OPTS += -DSQLITE4_OMIT_XFER_OPT
OPTS += -DSQLITE4_THREADSAFE=0

# This is how we compile
#
TCCX =  $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP) 







|

<







47
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
#OPTS += -DSQLITE4_DEBUG=1 -DLSM_DEBUG=1
OPTS += -DHAVE_GMTIME_R
OPTS += -DHAVE_LOCALTIME_R
OPTS += -DHAVE_MALLOC_USABLE_SIZE
OPTS += -DHAVE_USLEEP
#OPTS += -DSQLITE4_MEMDEBUG=1
#OPTS += -DSQLITE4_NO_SYNC=1 -DLSM_NO_SYNC=1
#OPTS += -DSQLITE4_OMIT_ANALYZE
OPTS += -DSQLITE4_OMIT_AUTOMATIC_INDEX

OPTS += -DSQLITE4_OMIT_VIRTUALTABLE=1
OPTS += -DSQLITE4_OMIT_XFER_OPT
OPTS += -DSQLITE4_THREADSAFE=0

# This is how we compile
#
TCCX =  $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP) 

Changes to src/analyze.c

14
15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
..
51
52
53
54
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
...
167
168
169
170
171
172
173

174
175
176
177

178
179
180
181
182

183

184
185
186
187
188
189
190
...
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
...
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
...
489
490
491
492
493
494
495




496
497
498
499
500
501
502
...
530
531
532
533
534
535
536
537



538
539
540
541
542
543
544
545
546
547
548
549



550


551
552
553
554
555
556
557
558
559
560

561

562
563
564
565
566
567
568
...
595
596
597
598
599
600
601

602
603
604
605
606
607
608
...
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
...
789
790
791
792
793
794
795
796
797
798
799


800
801
802
803
804
805
806
807
808
809
810
811
812
813
814


815
816
817
818
819
820
821
...
831
832
833
834
835
836
837
838
839
840
841
842
843





844
845
846
847
848



849
850
851
852
853
854
855

856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877

878
879
880
881

882
883
884
885
886
887
888
...
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
...
919
920
921
922
923
924
925

926
927
928
929
930
931
932
...
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
....
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
....
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099


1100

1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
** The ANALYZE command gather statistics about the content of tables
** and indices.  These statistics are made available to the query planner
** to help it make better decisions about how to perform queries.
**
** The following system tables are or have been supported:
**
**    CREATE TABLE sqlite_stat1(tbl, idx, stat);
**    CREATE TABLE sqlite_stat2(tbl, idx, sampleno, sample);
**    CREATE TABLE sqlite_stat3(tbl, idx, nEq, nLt, nDLt, sample);
**

** Additional tables might be added in future releases of SQLite.
** The sqlite_stat2 table is not created or used unless the SQLite version
** is between 3.6.18 and 3.7.8, inclusive, and unless SQLite is compiled
** with SQLITE4_ENABLE_STAT2.  The sqlite_stat2 table is deprecated.
** The sqlite_stat2 table is superceded by sqlite_stat3, which is only
** created and used by SQLite versions 3.7.9 and later and with
** SQLITE4_ENABLE_STAT3 defined.  The fucntionality of sqlite_stat3
** is a superset of sqlite_stat2.  
**
** Format of sqlite_stat1:
**
** There is normally one row per index, with the index identified by the
** name in the idx column.  The tbl column is the name of the table to
** which the index belongs.  In each such row, the stat column will be
** a string consisting of a list of integers.  The first integer in this
................................................................................
** "unordered" keyword is present, then the query planner assumes that
** the index is unordered and will not use the index for a range query.
** 
** If the sqlite_stat1.idx column is NULL, then the sqlite_stat1.stat
** column contains a single integer which is the (estimated) number of
** rows in the table identified by sqlite_stat1.tbl.
**
** Format of sqlite_stat2:
**
** The sqlite_stat2 is only created and is only used if SQLite is compiled
** with SQLITE4_ENABLE_STAT2 and if the SQLite version number is between
** 3.6.18 and 3.7.8.  The "stat2" table contains additional information
** about the distribution of keys within an index.  The index is identified by
** the "idx" column and the "tbl" column is the name of the table to which
** the index belongs.  There are usually 10 rows in the sqlite_stat2
** table for each index.
**
** The sqlite_stat2 entries for an index that have sampleno between 0 and 9
** inclusive are samples of the left-most key value in the index taken at
** evenly spaced points along the index.  Let the number of samples be S
** (10 in the standard build) and let C be the number of rows in the index.
** Then the sampled rows are given by:
**
**     rownumber = (i*C*2 + C)/(S*2)
**
** For i between 0 and S-1.  Conceptually, the index space is divided into
** S uniform buckets and the samples are the middle row from each bucket.
**
** The format for sqlite_stat2 is recorded here for legacy reference.  This
** version of SQLite does not support sqlite_stat2.  It neither reads nor
** writes the sqlite_stat2 table.  This version of SQLite only supports
** sqlite_stat3.
**
** Format for sqlite_stat3:
**
** The sqlite_stat3 is an enhancement to sqlite_stat2.  A new name is
** used to avoid compatibility problems.  
**
** The format of the sqlite_stat3 table is similar to the format of
** the sqlite_stat2 table.  There are multiple entries for each index.
** The idx column names the index and the tbl column is the table of the
** index.  If the idx and tbl columns are the same, then the sample is
** of the INTEGER PRIMARY KEY.  The sample column is a value taken from
** the left-most column of the index.  The nEq column is the approximate
** number of entires in the index whose left-most column exactly matches
** the sample.  nLt is the approximate number of entires whose left-most
** column is less than the sample.  The nDLt column is the approximate
** number of distinct left-most entries in the index that are less than
** the sample.
**
** Future versions of SQLite might change to store a string containing
** multiple integers values in the nDLt column of sqlite_stat3.  The first
** integer will be the number of prior index entires that are distinct in
** the left-most column.  The second integer will be the number of prior index
** entries that are distinct in the first two columns.  The third integer
** will be the number of prior index entries that are distinct in the first
** three columns.  And so forth.  With that extension, the nDLt field is
** similar in function to the sqlite_stat1.stat field.
**
** There can be an arbitrary number of sqlite_stat3 entries per index.
................................................................................
    const char *zTab = aTable[i].zName;
    Table *pStat;
    if( (pStat = sqlite4FindTable(db, zTab, pDb->zName))==0 ){
      /* The sqlite_stat[12] table does not exist. Create it. Note that a 
      ** side-effect of the CREATE TABLE statement is to leave the rootpage 
      ** of the new table in register pParse->regRoot. This is important 
      ** because the OpenWrite opcode below will be needing it. */

      sqlite4NestedParse(pParse,
          "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols
      );
      aRoot[i] = pParse->regRoot;

      aCreateTbl[i] = 1;
    }else{
      /* The table already exists. If zWhere is not NULL, delete all entries 
      ** associated with the table zWhere. If zWhere is NULL, delete the
      ** entire contents of the table. */

      aRoot[i] = pStat->tnum;

      if( zWhere ){
        sqlite4NestedParse(pParse,
           "DELETE FROM %Q.%s WHERE %s=%Q", pDb->zName, zTab, zWhereType, zWhere
        );
      }else{
        /* The sqlite_stat[12] table already exists.  Delete all rows. */
        sqlite4VdbeAddOp2(v, OP_Clear, aRoot[i], iDb);
................................................................................
  int argc,
  sqlite4_value **argv
){
  Stat3Accum *p;
  tRowcnt nRow;
  int mxSample;
  int n;
  sqlite4_env *pEnv = sqlite4_context_env(context);

  UNUSED_PARAMETER(argc);
  nRow = (tRowcnt)sqlite4_value_int64(argv[0]);
  mxSample = sqlite4_value_int(argv[1]);
  n = sizeof(*p) + sizeof(p->a[0])*mxSample;
  p = sqlite4_malloc(pEnv, n);
  if( p==0 ){
    sqlite4_result_error_nomem(context);
    return;
  }
  memset(p, 0, n);
  p->a = (struct Stat3Sample*)&p[1];
  p->nRow = nRow;
  p->mxSample = mxSample;
  p->nPSample = p->nRow/(mxSample/3+1) + 1;
  sqlite4_randomness(pEnv, sizeof(p->iPrn), &p->iPrn);
  sqlite4_result_blob(context, p, sizeof(p), SQLITE4_DYNAMIC);
}
static const FuncDef stat3InitFuncdef = {
  2,                /* nArg */
  SQLITE4_UTF8,      /* iPrefEnc */
  0,                /* flags */
  0,                /* pUserData */
  0,                /* pNext */
................................................................................
  int iTabCur = pParse->nTab++; /* Table cursor */
#endif
  int regCol = iMem++;         /* Content of a column in analyzed table */
  int regRec = iMem++;         /* Register holding completed record */
  int regTemp = iMem++;        /* Temporary use register */
  int regNewRowid = iMem++;    /* Rowid for the inserted record */


  v = sqlite4GetVdbe(pParse);
  if( v==0 || NEVER(pTab==0) ){
    return;
  }
  if( pTab->tnum==0 ){
    /* Do not gather statistics on views or virtual tables */
    return;
  }
  if( memcmp(pTab->zName, "sqlite_", 7)==0 ){
    /* Do not gather statistics on system tables */
    return;
  }
  iDb = sqlite4SchemaToIndex(db, pTab->pSchema);
  assert( iDb>=0 );
#ifndef SQLITE4_OMIT_AUTHORIZATION
  if( sqlite4AuthCheck(pParse, SQLITE4_ANALYZE, pTab->zName, 0,
................................................................................
  iIdxCur = pParse->nTab++;
  sqlite4VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0);
  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    int nCol;
    KeyInfo *pKey;
    int addrIfNot = 0;           /* address of OP_IfNot */
    int *aChngAddr;              /* Array of jump instruction addresses */





    if( pOnlyIdx && pOnlyIdx!=pIdx ) continue;
    VdbeNoopComment((v, "Begin analysis of %s", pIdx->zName));
    nCol = pIdx->nColumn;
    aChngAddr = sqlite4DbMallocRaw(db, sizeof(int)*nCol);
    if( aChngAddr==0 ) continue;
    pKey = sqlite4IndexKeyinfo(pParse, pIdx);
................................................................................
#endif /* SQLITE4_ENABLE_STAT3 */

    /* The block of memory cells initialized here is used as follows.
    **
    **    iMem:                
    **        The total number of rows in the table.
    **
    **    iMem+1 .. iMem+nCol: 



    **        Number of distinct entries in index considering the 
    **        left-most N columns only, where N is between 1 and nCol, 
    **        inclusive.
    **
    **    iMem+nCol+1 .. Mem+2*nCol:  
    **        Previous value of indexed columns, from left to right.
    **
    ** Cells iMem through iMem+nCol are initialized to 0. The others are 
    ** initialized to contain an SQL NULL.
    */
    for(i=0; i<=nCol; i++){
      sqlite4VdbeAddOp2(v, OP_Integer, 0, iMem+i);



    }


    for(i=0; i<nCol; i++){
      sqlite4VdbeAddOp2(v, OP_Null, 0, iMem+nCol+i+1);
    }

    /* Start the analysis loop. This loop runs through all the entries in
    ** the index b-tree.  */
    endOfLoop = sqlite4VdbeMakeLabel(v);
    sqlite4VdbeAddOp2(v, OP_Rewind, iIdxCur, endOfLoop);
    topOfLoop = sqlite4VdbeCurrentAddr(v);
    sqlite4VdbeAddOp2(v, OP_AddImm, iMem, 1);  /* Increment row counter */



    for(i=0; i<nCol; i++){
      CollSeq *pColl;
      sqlite4VdbeAddOp3(v, OP_Column, iIdxCur, i, regCol);
      if( i==0 ){
        /* Always record the very first row */
        addrIfNot = sqlite4VdbeAddOp1(v, OP_IfNot, iMem+1);
      }
................................................................................
        sqlite4VdbeAddOp2(v, OP_Integer, 1, regNumEq);
#endif        
      }
      sqlite4VdbeAddOp2(v, OP_AddImm, iMem+i+1, 1);
      sqlite4VdbeAddOp3(v, OP_Column, iIdxCur, i, iMem+nCol+i+1);
    }
    sqlite4DbFree(db, aChngAddr);


    /* Always jump here after updating the iMem+1...iMem+1+nCol counters */
    sqlite4VdbeResolveLabel(v, endOfLoop);

    sqlite4VdbeAddOp2(v, OP_Next, iIdxCur, topOfLoop);
    sqlite4VdbeAddOp1(v, OP_Close, iIdxCur);
#ifdef SQLITE4_ENABLE_STAT3
................................................................................
    sqlite4VdbeAddOp2(v, OP_SCopy, iMem, regStat1);
    if( jZeroRows<0 ){
      jZeroRows = sqlite4VdbeAddOp1(v, OP_IfNot, iMem);
    }
    for(i=0; i<nCol; i++){
      sqlite4VdbeAddOp4(v, OP_String8, 0, regTemp, 0, " ", 0);
      sqlite4VdbeAddOp3(v, OP_Concat, regTemp, regStat1, regStat1);
      sqlite4VdbeAddOp3(v, OP_Add, iMem, iMem+i+1, regTemp);
      sqlite4VdbeAddOp2(v, OP_AddImm, regTemp, -1);
      sqlite4VdbeAddOp3(v, OP_Divide, iMem+i+1, regTemp, regTemp);
      sqlite4VdbeAddOp1(v, OP_ToInt, regTemp);
      sqlite4VdbeAddOp3(v, OP_Concat, regTemp, regStat1, regStat1);
    }
    sqlite4VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
    sqlite4VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
    sqlite4VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid);
    sqlite4VdbeChangeP5(v, OPFLAG_APPEND);
  }

  /* If the table has no indices, create a single sqlite_stat1 entry
  ** containing NULL as the index name and the row count as the content.
  */
  if( pTab->pIndex==0 ){
    sqlite4VdbeAddOp3(v, OP_OpenRead, iIdxCur, pTab->tnum, iDb);
    VdbeComment((v, "%s", pTab->zName));
    sqlite4VdbeAddOp2(v, OP_Count, iIdxCur, regStat1);
    sqlite4VdbeAddOp1(v, OP_Close, iIdxCur);
    jZeroRows = sqlite4VdbeAddOp1(v, OP_IfNot, regStat1);
  }else{
    sqlite4VdbeJumpHere(v, jZeroRows);
    jZeroRows = sqlite4VdbeAddOp0(v, OP_Goto);
  }
  sqlite4VdbeAddOp2(v, OP_Null, 0, regIdxname);
  sqlite4VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
  sqlite4VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
  sqlite4VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid);
  sqlite4VdbeChangeP5(v, OPFLAG_APPEND);
  if( pParse->nMem<regRec ) pParse->nMem = regRec;
  sqlite4VdbeJumpHere(v, jZeroRows);
................................................................................
    /* Form 2:  Analyze the database or table named */
    iDb = sqlite4FindDb(db, pName1);
    if( iDb>=0 ){
      analyzeDatabase(pParse, iDb);
    }else{
      z = sqlite4NameFromToken(db, pName1);
      if( z ){
        if( (pIdx = sqlite4FindIndex(db, z, 0))!=0 ){
          analyzeTable(pParse, pIdx->pTable, pIdx);
        }else if( (pTab = sqlite4LocateTable(pParse, 0, z, 0))!=0 ){
          analyzeTable(pParse, pTab, 0);


        }
        sqlite4DbFree(db, z);
      }
    }
  }else{
    /* Form 3: Analyze the fully qualified table name */
    iDb = sqlite4TwoPartName(pParse, pName1, pName2, &pTableName);
    if( iDb>=0 ){
      zDb = db->aDb[iDb].zName;
      z = sqlite4NameFromToken(db, pTableName);
      if( z ){
        if( (pIdx = sqlite4FindIndex(db, z, zDb))!=0 ){
          analyzeTable(pParse, pIdx->pTable, pIdx);
        }else if( (pTab = sqlite4LocateTable(pParse, 0, z, zDb))!=0 ){
          analyzeTable(pParse, pTab, 0);


        }
        sqlite4DbFree(db, z);
      }
    }   
  }
}

................................................................................

/*
** This callback is invoked once for each index when reading the
** sqlite_stat1 table.  
**
**     argv[0] = name of the table
**     argv[1] = name of the index (might be NULL)
**     argv[2] = results of analysis - on integer for each column
**
** Entries for which argv[1]==NULL simply record the number of rows in
** the table.
*/
static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){





  analysisInfo *pInfo = (analysisInfo*)pData;
  Index *pIndex;
  Table *pTable;
  int i, c, n;
  tRowcnt v;



  const char *z;

  assert( argc==3 );
  UNUSED_PARAMETER2(NotUsed, argc);

  if( argv==0 || argv[0]==0 || argv[2]==0 ){
    return 0;

  }
  pTable = sqlite4FindTable(pInfo->db, argv[0], pInfo->zDatabase);
  if( pTable==0 ){
    return 0;
  }
  if( argv[1] ){
    pIndex = sqlite4FindIndex(pInfo->db, argv[1], pInfo->zDatabase);
  }else{
    pIndex = 0;
  }
  n = pIndex ? pIndex->nColumn : 0;
  z = argv[2];
  for(i=0; *z && i<=n; i++){
    v = 0;
    while( (c=z[0])>='0' && c<='9' ){
      v = v*10 + c - '0';
      z++;
    }
    if( i==0 ) pTable->nRowEst = v;
    if( pIndex==0 ) break;
    pIndex->aiRowEst[i] = v;
    if( *z==' ' ) z++;

    if( memcmp(z, "unordered", 10)==0 ){
      pIndex->bUnordered = 1;
      break;
    }

  }
  return 0;
}

/*
** If the Index.aSample variable is not NULL, delete the aSample[] array
** and its contents.
................................................................................
*/
void sqlite4DeleteIndexSamples(sqlite4 *db, Index *pIdx){
#ifdef SQLITE4_ENABLE_STAT3
  if( pIdx->aSample ){
    int j;
    for(j=0; j<pIdx->nSample; j++){
      IndexSample *p = &pIdx->aSample[j];
      if( p->eType==SQLITE4_TEXT || p->eType==SQLITE4_BLOB ){
        sqlite4DbFree(db, p->u.z);
      }
    }
    sqlite4DbFree(db, pIdx->aSample);
  }
  if( db && db->pnBytesFreed==0 ){
    pIdx->nSample = 0;
................................................................................
  sqlite4_stmt *pStmt = 0;      /* An SQL statement being run */
  char *zSql;                   /* Text of the SQL statement */
  Index *pPrevIdx = 0;          /* Previous index in the loop */
  int idx = 0;                  /* slot in pIdx->aSample[] for next sample */
  int eType;                    /* Datatype of a sample */
  IndexSample *pSample;         /* A slot in pIdx->aSample[] */


  if( !sqlite4FindTable(db, "sqlite_stat3", zDb) ){
    return SQLITE4_OK;
  }

  zSql = sqlite4MPrintf(db, 
      "SELECT idx,count(*) FROM %Q.sqlite_stat3"
      " GROUP BY idx", zDb);
................................................................................
    zIndex = (char *)sqlite4_column_text(pStmt, 0);
    if( zIndex==0 ) continue;
    nSample = sqlite4_column_int(pStmt, 1);
    pIdx = sqlite4FindIndex(db, zIndex, zDb);
    if( pIdx==0 ) continue;
    assert( pIdx->nSample==0 );
    pIdx->nSample = nSample;
    pIdx->aSample = sqlite4MallocZero(db->pEnv, nSample*sizeof(IndexSample) );
    pIdx->avgEq = pIdx->aiRowEst[1];
    if( pIdx->aSample==0 ){
      db->mallocFailed = 1;
      sqlite4_finalize(pStmt);
      return SQLITE4_NOMEM;
    }
  }
................................................................................
      case SQLITE4_FLOAT: {
        pSample->u.r = sqlite4_column_double(pStmt, 4);
        break;
      }
      case SQLITE4_NULL: {
        break;
      }
      default: assert( eType==SQLITE4_TEXT || eType==SQLITE4_BLOB ); {
        const char *z = (const char *)(
              (eType==SQLITE4_BLOB) ?
              sqlite4_column_blob(pStmt, 4):
              sqlite4_column_text(pStmt, 4)
           );
        int n = z ? sqlite4_column_bytes(pStmt, 4) : 0;
        pSample->nByte = n;
        if( n < 1){
          pSample->u.z = 0;
        }else{
          pSample->u.z = sqlite4Malloc(db->pEnv, n);
          if( pSample->u.z==0 ){
            db->mallocFailed = 1;
            sqlite4_finalize(pStmt);
            return SQLITE4_NOMEM;
          }
          memcpy(pSample->u.z, z, n);
        }
................................................................................

  /* Load new statistics out of the sqlite_stat1 table */
  zSql = sqlite4MPrintf(db, 
      "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
  if( zSql==0 ){
    rc = SQLITE4_NOMEM;
  }else{
    rc = sqlite4_exec(db, zSql, analysisLoader, &sInfo, 0);
    sqlite4DbFree(db, zSql);
  }


  /* Load the statistics from the sqlite_stat3 table. */
#ifdef SQLITE4_ENABLE_STAT3
  if( rc==SQLITE4_OK ){


    rc = loadStat3(db, sInfo.zDatabase);

  }
#endif

  if( rc==SQLITE4_NOMEM ){
    db->mallocFailed = 1;
  }
  return rc;
}


#endif /* SQLITE4_OMIT_ANALYZE */







<


>
|
<
<
<
<
<
<
<







 







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


<
<
<
<
|












|







 







>



|
>





>
|
>







 







<





|




<




|
|







 







<




|



|







 







>
>
>
>







 







|
>
>
>



<
<
<
<
<
<

<
<
>
>
>
|
>
>

|







|
>

>







 







>







 







|

|









<
<
<
<
<
<
<
<
<
<
|
|
<







 







<
<
|

>
>











<
<
|

>
>







 







|




|
>
>
>
>
>





>
>
>
|

|
|

<
<
>
|
|



<
|
<
<
|

<










>
|



>







 







|







 







>







 







|







 







|










|







 







|







>
>

>











14
15
16
17
18
19
20

21
22
23
24







25
26
27
28
29
30
31
..
44
45
46
47
48
49
50


























51
52




53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
...
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
...
212
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
241
...
425
426
427
428
429
430
431

432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
...
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
...
498
499
500
501
502
503
504
505
506
507
508
509
510
511






512


513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
...
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
...
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645










646
647

648
649
650
651
652
653
654
...
749
750
751
752
753
754
755


756
757
758
759
760
761
762
763
764
765
766
767
768
769
770


771
772
773
774
775
776
777
778
779
780
781
...
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821


822
823
824
825
826
827

828


829
830

831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
...
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
...
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
...
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
...
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
....
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
1080
** The ANALYZE command gather statistics about the content of tables
** and indices.  These statistics are made available to the query planner
** to help it make better decisions about how to perform queries.
**
** The following system tables are or have been supported:
**
**    CREATE TABLE sqlite_stat1(tbl, idx, stat);

**    CREATE TABLE sqlite_stat3(tbl, idx, nEq, nLt, nDLt, sample);
**
** The sqlite_stat3 table is only created if SQLITE4_ENABLE_STAT3 is
** defined.







**
** Format of sqlite_stat1:
**
** There is normally one row per index, with the index identified by the
** name in the idx column.  The tbl column is the name of the table to
** which the index belongs.  In each such row, the stat column will be
** a string consisting of a list of integers.  The first integer in this
................................................................................
** "unordered" keyword is present, then the query planner assumes that
** the index is unordered and will not use the index for a range query.
** 
** If the sqlite_stat1.idx column is NULL, then the sqlite_stat1.stat
** column contains a single integer which is the (estimated) number of
** rows in the table identified by sqlite_stat1.tbl.
**


























** Format for sqlite_stat3:
**




** The sqlite_stat3 table may contain multiple entries for each index.
** The idx column names the index and the tbl column is the table of the
** index.  If the idx and tbl columns are the same, then the sample is
** of the INTEGER PRIMARY KEY.  The sample column is a value taken from
** the left-most column of the index.  The nEq column is the approximate
** number of entires in the index whose left-most column exactly matches
** the sample.  nLt is the approximate number of entires whose left-most
** column is less than the sample.  The nDLt column is the approximate
** number of distinct left-most entries in the index that are less than
** the sample.
**
** Future versions of SQLite might change to store a string containing
** multiple integers values in the nDLt column of sqlite_stat3.  The first
** integer will be the number of prior index entries that are distinct in
** the left-most column.  The second integer will be the number of prior index
** entries that are distinct in the first two columns.  The third integer
** will be the number of prior index entries that are distinct in the first
** three columns.  And so forth.  With that extension, the nDLt field is
** similar in function to the sqlite_stat1.stat field.
**
** There can be an arbitrary number of sqlite_stat3 entries per index.
................................................................................
    const char *zTab = aTable[i].zName;
    Table *pStat;
    if( (pStat = sqlite4FindTable(db, zTab, pDb->zName))==0 ){
      /* The sqlite_stat[12] table does not exist. Create it. Note that a 
      ** side-effect of the CREATE TABLE statement is to leave the rootpage 
      ** of the new table in register pParse->regRoot. This is important 
      ** because the OpenWrite opcode below will be needing it. */
      pParse->pPKRoot = &aRoot[i];
      sqlite4NestedParse(pParse,
          "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols
      );
      assert( pParse->nErr>0 || aRoot[i]>0 );
      pParse->pPKRoot = 0;
      aCreateTbl[i] = 1;
    }else{
      /* The table already exists. If zWhere is not NULL, delete all entries 
      ** associated with the table zWhere. If zWhere is NULL, delete the
      ** entire contents of the table. */
      Index *pPK = sqlite4FindPrimaryKey(pStat, 0);
      aRoot[i] = pPK->tnum;
      assert( aRoot[i]>0 );
      if( zWhere ){
        sqlite4NestedParse(pParse,
           "DELETE FROM %Q.%s WHERE %s=%Q", pDb->zName, zTab, zWhereType, zWhere
        );
      }else{
        /* The sqlite_stat[12] table already exists.  Delete all rows. */
        sqlite4VdbeAddOp2(v, OP_Clear, aRoot[i], iDb);
................................................................................
  int argc,
  sqlite4_value **argv
){
  Stat3Accum *p;
  tRowcnt nRow;
  int mxSample;
  int n;


  UNUSED_PARAMETER(argc);
  nRow = (tRowcnt)sqlite4_value_int64(argv[0]);
  mxSample = sqlite4_value_int(argv[1]);
  n = sizeof(*p) + sizeof(p->a[0])*mxSample;
  p = sqlite4MallocZero( n );
  if( p==0 ){
    sqlite4_result_error_nomem(context);
    return;
  }

  p->a = (struct Stat3Sample*)&p[1];
  p->nRow = nRow;
  p->mxSample = mxSample;
  p->nPSample = p->nRow/(mxSample/3+1) + 1;
  sqlite4_randomness(sizeof(p->iPrn), &p->iPrn);
  sqlite4_result_blob(context, p, sizeof(p), sqlite4_free);
}
static const FuncDef stat3InitFuncdef = {
  2,                /* nArg */
  SQLITE4_UTF8,      /* iPrefEnc */
  0,                /* flags */
  0,                /* pUserData */
  0,                /* pNext */
................................................................................
  int iTabCur = pParse->nTab++; /* Table cursor */
#endif
  int regCol = iMem++;         /* Content of a column in analyzed table */
  int regRec = iMem++;         /* Register holding completed record */
  int regTemp = iMem++;        /* Temporary use register */
  int regNewRowid = iMem++;    /* Rowid for the inserted record */


  v = sqlite4GetVdbe(pParse);
  if( v==0 || NEVER(pTab==0) ){
    return;
  }
  if( pTab->pIndex==0 ){
    /* Do not gather statistics on views or virtual tables */
    return;
  }
  if( sqlite4_strnicmp(pTab->zName, "sqlite_", 7)==0 ){
    /* Do not gather statistics on system tables */
    return;
  }
  iDb = sqlite4SchemaToIndex(db, pTab->pSchema);
  assert( iDb>=0 );
#ifndef SQLITE4_OMIT_AUTHORIZATION
  if( sqlite4AuthCheck(pParse, SQLITE4_ANALYZE, pTab->zName, 0,
................................................................................
  iIdxCur = pParse->nTab++;
  sqlite4VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0);
  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    int nCol;
    KeyInfo *pKey;
    int addrIfNot = 0;           /* address of OP_IfNot */
    int *aChngAddr;              /* Array of jump instruction addresses */

    int regCnt;                  /* Total number of rows in table. */
    int regPrev;                 /* Previous index key read from database */
    int aregCard;                /* Cardinality array registers */

    if( pOnlyIdx && pOnlyIdx!=pIdx ) continue;
    VdbeNoopComment((v, "Begin analysis of %s", pIdx->zName));
    nCol = pIdx->nColumn;
    aChngAddr = sqlite4DbMallocRaw(db, sizeof(int)*nCol);
    if( aChngAddr==0 ) continue;
    pKey = sqlite4IndexKeyinfo(pParse, pIdx);
................................................................................
#endif /* SQLITE4_ENABLE_STAT3 */

    /* The block of memory cells initialized here is used as follows.
    **
    **    iMem:                
    **        The total number of rows in the table.
    **
    **    iMem+1:
    **        Previous record read from index.
    **
    **    iMem+1+1 .. iMem+1+nCol: 
    **        Number of distinct entries in index considering the 
    **        left-most N columns only, where N is between 1 and nCol, 
    **        inclusive.






    */


    regCnt = iMem;
    regPrev = iMem+1;
    aregCard = iMem+2;

    sqlite4VdbeAddOp2(v, OP_Integer, 0, regCnt);
    sqlite4VdbeAddOp2(v, OP_Null, 0, regPrev);
    for(i=0; i<nCol; i++){
      sqlite4VdbeAddOp2(v, OP_Integer, 1, aregCard+i);
    }

    /* Start the analysis loop. This loop runs through all the entries in
    ** the index b-tree.  */
    endOfLoop = sqlite4VdbeMakeLabel(v);
    sqlite4VdbeAddOp2(v, OP_Rewind, iIdxCur, endOfLoop);
    topOfLoop = sqlite4VdbeCurrentAddr(v);
    sqlite4VdbeAddOp2(v, OP_AddImm, regCnt, 1);  /* Increment row counter */
    sqlite4VdbeAddOp4Int(v, OP_AnalyzeKey, iIdxCur, regPrev, aregCard, nCol);

#if 0
    for(i=0; i<nCol; i++){
      CollSeq *pColl;
      sqlite4VdbeAddOp3(v, OP_Column, iIdxCur, i, regCol);
      if( i==0 ){
        /* Always record the very first row */
        addrIfNot = sqlite4VdbeAddOp1(v, OP_IfNot, iMem+1);
      }
................................................................................
        sqlite4VdbeAddOp2(v, OP_Integer, 1, regNumEq);
#endif        
      }
      sqlite4VdbeAddOp2(v, OP_AddImm, iMem+i+1, 1);
      sqlite4VdbeAddOp3(v, OP_Column, iIdxCur, i, iMem+nCol+i+1);
    }
    sqlite4DbFree(db, aChngAddr);
#endif

    /* Always jump here after updating the iMem+1...iMem+1+nCol counters */
    sqlite4VdbeResolveLabel(v, endOfLoop);

    sqlite4VdbeAddOp2(v, OP_Next, iIdxCur, topOfLoop);
    sqlite4VdbeAddOp1(v, OP_Close, iIdxCur);
#ifdef SQLITE4_ENABLE_STAT3
................................................................................
    sqlite4VdbeAddOp2(v, OP_SCopy, iMem, regStat1);
    if( jZeroRows<0 ){
      jZeroRows = sqlite4VdbeAddOp1(v, OP_IfNot, iMem);
    }
    for(i=0; i<nCol; i++){
      sqlite4VdbeAddOp4(v, OP_String8, 0, regTemp, 0, " ", 0);
      sqlite4VdbeAddOp3(v, OP_Concat, regTemp, regStat1, regStat1);
      sqlite4VdbeAddOp3(v, OP_Add, iMem, aregCard+i, regTemp);
      sqlite4VdbeAddOp2(v, OP_AddImm, regTemp, -1);
      sqlite4VdbeAddOp3(v, OP_Divide, aregCard+i, regTemp, regTemp);
      sqlite4VdbeAddOp1(v, OP_ToInt, regTemp);
      sqlite4VdbeAddOp3(v, OP_Concat, regTemp, regStat1, regStat1);
    }
    sqlite4VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
    sqlite4VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
    sqlite4VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid);
    sqlite4VdbeChangeP5(v, OPFLAG_APPEND);
  }











  sqlite4VdbeJumpHere(v, jZeroRows);
  jZeroRows = sqlite4VdbeAddOp0(v, OP_Goto);

  sqlite4VdbeAddOp2(v, OP_Null, 0, regIdxname);
  sqlite4VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
  sqlite4VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
  sqlite4VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid);
  sqlite4VdbeChangeP5(v, OPFLAG_APPEND);
  if( pParse->nMem<regRec ) pParse->nMem = regRec;
  sqlite4VdbeJumpHere(v, jZeroRows);
................................................................................
    /* Form 2:  Analyze the database or table named */
    iDb = sqlite4FindDb(db, pName1);
    if( iDb>=0 ){
      analyzeDatabase(pParse, iDb);
    }else{
      z = sqlite4NameFromToken(db, pName1);
      if( z ){


        if( (pTab = sqlite4LocateTable(pParse, 0, z, 0))!=0 ){
          analyzeTable(pParse, pTab, 0);
        }else if( (pIdx = sqlite4FindIndex(db, z, 0))!=0 ){
          analyzeTable(pParse, pIdx->pTable, pIdx);
        }
        sqlite4DbFree(db, z);
      }
    }
  }else{
    /* Form 3: Analyze the fully qualified table name */
    iDb = sqlite4TwoPartName(pParse, pName1, pName2, &pTableName);
    if( iDb>=0 ){
      zDb = db->aDb[iDb].zName;
      z = sqlite4NameFromToken(db, pTableName);
      if( z ){


        if( (pTab = sqlite4LocateTable(pParse, 0, z, zDb))!=0 ){
          analyzeTable(pParse, pTab, 0);
        }else if( (pIdx = sqlite4FindIndex(db, z, zDb))!=0 ){
          analyzeTable(pParse, pIdx->pTable, pIdx);
        }
        sqlite4DbFree(db, z);
      }
    }   
  }
}

................................................................................

/*
** This callback is invoked once for each index when reading the
** sqlite_stat1 table.  
**
**     argv[0] = name of the table
**     argv[1] = name of the index (might be NULL)
**     argv[2] = results of analysis - one integer for each column
**
** Entries for which argv[1]==NULL simply record the number of rows in
** the table.
*/
static int analysisLoader(
  void *pData,                    /* Pointer to analysisInfo structure */
  int nVal,                       /* Size of apVal[] array */
  sqlite4_value **apVal,          /* Values for current row */
  const char **NotUsed            /* Column names (not used by this function) */
){
  analysisInfo *pInfo = (analysisInfo*)pData;
  Index *pIndex;
  Table *pTable;
  int i, c, n;
  tRowcnt v;

  const char *zTab = sqlite4_value_text(apVal[0], 0);
  const char *zIdx = sqlite4_value_text(apVal[1], 0);
  const char *z = sqlite4_value_text(apVal[2], 0);

  assert( nVal==3 );
  UNUSED_PARAMETER2(NotUsed, nVal);



  if( zTab==0 || zIdx==0 || z==0 ) return 0;

  pTable = sqlite4FindTable(pInfo->db, zTab, pInfo->zDatabase);
  if( pTable==0 ){
    return 0;
  }

  pIndex = sqlite4FindIndex(pInfo->db, zIdx, pInfo->zDatabase);



  n = pIndex ? pIndex->nColumn : 0;

  for(i=0; *z && i<=n; i++){
    v = 0;
    while( (c=z[0])>='0' && c<='9' ){
      v = v*10 + c - '0';
      z++;
    }
    if( i==0 ) pTable->nRowEst = v;
    if( pIndex==0 ) break;
    pIndex->aiRowEst[i] = v;
    if( *z==' ' ) z++;
#if 0
    if( strcmp(z, "unordered")==0 ){
      pIndex->bUnordered = 1;
      break;
    }
#endif
  }
  return 0;
}

/*
** If the Index.aSample variable is not NULL, delete the aSample[] array
** and its contents.
................................................................................
*/
void sqlite4DeleteIndexSamples(sqlite4 *db, Index *pIdx){
#ifdef SQLITE4_ENABLE_STAT3
  if( pIdx->aSample ){
    int j;
    for(j=0; j<pIdx->nSample; j++){
      IndexSample *p = &pIdx->aSample[j];
      if( p->eType==SQLITE4_TEXT || p->eType==SQLITE_BLOB ){
        sqlite4DbFree(db, p->u.z);
      }
    }
    sqlite4DbFree(db, pIdx->aSample);
  }
  if( db && db->pnBytesFreed==0 ){
    pIdx->nSample = 0;
................................................................................
  sqlite4_stmt *pStmt = 0;      /* An SQL statement being run */
  char *zSql;                   /* Text of the SQL statement */
  Index *pPrevIdx = 0;          /* Previous index in the loop */
  int idx = 0;                  /* slot in pIdx->aSample[] for next sample */
  int eType;                    /* Datatype of a sample */
  IndexSample *pSample;         /* A slot in pIdx->aSample[] */

  assert( db->lookaside.bEnabled==0 );
  if( !sqlite4FindTable(db, "sqlite_stat3", zDb) ){
    return SQLITE4_OK;
  }

  zSql = sqlite4MPrintf(db, 
      "SELECT idx,count(*) FROM %Q.sqlite_stat3"
      " GROUP BY idx", zDb);
................................................................................
    zIndex = (char *)sqlite4_column_text(pStmt, 0);
    if( zIndex==0 ) continue;
    nSample = sqlite4_column_int(pStmt, 1);
    pIdx = sqlite4FindIndex(db, zIndex, zDb);
    if( pIdx==0 ) continue;
    assert( pIdx->nSample==0 );
    pIdx->nSample = nSample;
    pIdx->aSample = sqlite4DbMallocZero(db, nSample*sizeof(IndexSample));
    pIdx->avgEq = pIdx->aiRowEst[1];
    if( pIdx->aSample==0 ){
      db->mallocFailed = 1;
      sqlite4_finalize(pStmt);
      return SQLITE4_NOMEM;
    }
  }
................................................................................
      case SQLITE4_FLOAT: {
        pSample->u.r = sqlite4_column_double(pStmt, 4);
        break;
      }
      case SQLITE4_NULL: {
        break;
      }
      default: assert( eType==SQLITE4_TEXT || eType==SQLITE_BLOB ); {
        const char *z = (const char *)(
              (eType==SQLITE4_BLOB) ?
              sqlite4_column_blob(pStmt, 4):
              sqlite4_column_text(pStmt, 4)
           );
        int n = z ? sqlite4_column_bytes(pStmt, 4) : 0;
        pSample->nByte = n;
        if( n < 1){
          pSample->u.z = 0;
        }else{
          pSample->u.z = sqlite4DbMallocRaw(db, n);
          if( pSample->u.z==0 ){
            db->mallocFailed = 1;
            sqlite4_finalize(pStmt);
            return SQLITE4_NOMEM;
          }
          memcpy(pSample->u.z, z, n);
        }
................................................................................

  /* Load new statistics out of the sqlite_stat1 table */
  zSql = sqlite4MPrintf(db, 
      "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
  if( zSql==0 ){
    rc = SQLITE4_NOMEM;
  }else{
    rc = sqlite4_exec(db, zSql, analysisLoader, &sInfo);
    sqlite4DbFree(db, zSql);
  }


  /* Load the statistics from the sqlite_stat3 table. */
#ifdef SQLITE4_ENABLE_STAT3
  if( rc==SQLITE4_OK ){
    int lookasideEnabled = db->lookaside.bEnabled;
    db->lookaside.bEnabled = 0;
    rc = loadStat3(db, sInfo.zDatabase);
    db->lookaside.bEnabled = lookasideEnabled;
  }
#endif

  if( rc==SQLITE4_NOMEM ){
    db->mallocFailed = 1;
  }
  return rc;
}


#endif /* SQLITE4_OMIT_ANALYZE */

Changes to src/build.c

1488
1489
1490
1491
1492
1493
1494

1495








1496
1497
1498
1499
1500
1501
1502
....
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366

2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
      /* If no explicit PRIMARY KEY has been created, add an implicit 
      ** primary key here.  An implicit primary key works the way "rowid" 
      ** did in SQLite 3.  */
      addImplicitPrimaryKey(pParse, p, iDb);
    }
    pPk = sqlite4FindPrimaryKey(p, 0);
    assert( pPk || pParse->nErr || db->mallocFailed );

    if( pPk ) iPkRoot = pPk->tnum;








  }

#ifndef SQLITE4_OMIT_CHECK
  /* Resolve names in all CHECK constraint expressions.
  */
  if( p->pCheck ){
    SrcList sSrc;                   /* Fake SrcList for pParse->pNewTable */
................................................................................
  pTab = sqlite4SrcListLookup(pParse, p->pTblName);
  if( !pTab || db->mallocFailed ) return 0;
  assert( db->aDb[iDb].pSchema==pTab->pSchema );
  assert( pParse->nErr==0 );

  /* TODO: We will need to reinstate this block when sqlite_master is 
  ** modified to use an implicit primary key.  */
#if 0
  if( sqlite4_strnicmp(pTab->zName, "sqlite_", 7)==0 
       && memcmp(&pTab->zName[7],"altertab_",9)!=0 ){

    sqlite4ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
    goto exit_create_index;
  }
#endif

  /* Verify that this is not an attempt to create an index on a view or
  ** virtual table. */
  if( IsView(pTab) ){
    sqlite4ErrorMsg(pParse, "views may not be indexed");
    return 0;
  }







>
|
>
>
>
>
>
>
>
>







 







<

|
>

|

<







1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
....
2366
2367
2368
2369
2370
2371
2372

2373
2374
2375
2376
2377
2378

2379
2380
2381
2382
2383
2384
2385
      /* If no explicit PRIMARY KEY has been created, add an implicit 
      ** primary key here.  An implicit primary key works the way "rowid" 
      ** did in SQLite 3.  */
      addImplicitPrimaryKey(pParse, p, iDb);
    }
    pPk = sqlite4FindPrimaryKey(p, 0);
    assert( pPk || pParse->nErr || db->mallocFailed );
    if( pPk ){
      iPkRoot = pPk->tnum;
      if( pParse->pPKRoot ){
        /* If pParse->pPKRoto is non-zero, it is a pointer to a location in
        ** which to store the root page number of the table just created. 
        ** This is used by the ANALYZE command when creating the sqlite_stat*
        ** tables.  */
        *pParse->pPKRoot = iPkRoot;
      }
    }
  }

#ifndef SQLITE4_OMIT_CHECK
  /* Resolve names in all CHECK constraint expressions.
  */
  if( p->pCheck ){
    SrcList sSrc;                   /* Fake SrcList for pParse->pNewTable */
................................................................................
  pTab = sqlite4SrcListLookup(pParse, p->pTblName);
  if( !pTab || db->mallocFailed ) return 0;
  assert( db->aDb[iDb].pSchema==pTab->pSchema );
  assert( pParse->nErr==0 );

  /* TODO: We will need to reinstate this block when sqlite_master is 
  ** modified to use an implicit primary key.  */

  if( sqlite4_strnicmp(pTab->zName, "sqlite_", 7)==0 
   && memcmp(&pTab->zName[7],"altertab_",9)!=0 
  ){
    sqlite4ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
    return 0;
  }


  /* Verify that this is not an attempt to create an index on a view or
  ** virtual table. */
  if( IsView(pTab) ){
    sqlite4ErrorMsg(pParse, "views may not be indexed");
    return 0;
  }

Changes to src/sqliteInt.h

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
....
2166
2167
2168
2169
2170
2171
2172

2173
2174
2175
2176
2177
2178
2179
*************************************************************************
** Internal interface definitions for SQLite.
**
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

#define SQLITE4_OMIT_ANALYZE 1
#define SQLITE4_OMIT_PROGRESS_CALLBACK 1
#define SQLITE4_OMIT_VIRTUALTABLE 1
#define SQLITE4_OMIT_XFER_OPT 1
#define SQLITE4_OMIT_LOCALTIME 1

/*
** These #defines should enable >2GB file support on POSIX if the
................................................................................
  yDbMask writeMask;   /* Start a write transaction on these databases */
  yDbMask cookieMask;  /* Bitmask of schema verified databases */
  u8 isMultiWrite;     /* True if statement may affect/insert multiple rows */
  u8 mayAbort;         /* True if statement may throw an ABORT exception */
  int cookieGoto;      /* Address of OP_Goto to cookie verifier subroutine */
  int cookieValue[SQLITE4_MAX_ATTACHED+2];  /* Values of cookies to verify */
  int regRowid;        /* Register holding rowid of CREATE TABLE entry */

  AutoincInfo *pAinc;  /* Information about AUTOINCREMENT counters */
  int nMaxArg;         /* Max args passed to user function by sub-program */

  /* Information used while coding trigger programs. */
  Parse *pToplevel;    /* Parse structure for main program (or NULL) */
  Table *pTriggerTab;  /* Table triggers are being coded for */
  u32 oldmask;         /* Mask of old.* columns referenced */







<







 







>







11
12
13
14
15
16
17

18
19
20
21
22
23
24
....
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
*************************************************************************
** Internal interface definitions for SQLite.
**
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_


#define SQLITE4_OMIT_PROGRESS_CALLBACK 1
#define SQLITE4_OMIT_VIRTUALTABLE 1
#define SQLITE4_OMIT_XFER_OPT 1
#define SQLITE4_OMIT_LOCALTIME 1

/*
** These #defines should enable >2GB file support on POSIX if the
................................................................................
  yDbMask writeMask;   /* Start a write transaction on these databases */
  yDbMask cookieMask;  /* Bitmask of schema verified databases */
  u8 isMultiWrite;     /* True if statement may affect/insert multiple rows */
  u8 mayAbort;         /* True if statement may throw an ABORT exception */
  int cookieGoto;      /* Address of OP_Goto to cookie verifier subroutine */
  int cookieValue[SQLITE4_MAX_ATTACHED+2];  /* Values of cookies to verify */
  int regRowid;        /* Register holding rowid of CREATE TABLE entry */
  int *pPKRoot;        /* if !=0, CREATE TABLE should store root of PK here */
  AutoincInfo *pAinc;  /* Information about AUTOINCREMENT counters */
  int nMaxArg;         /* Max args passed to user function by sub-program */

  /* Information used while coding trigger programs. */
  Parse *pToplevel;    /* Parse structure for main program (or NULL) */
  Table *pTriggerTab;  /* Table triggers are being coded for */
  u32 oldmask;         /* Mask of old.* columns referenced */

Changes to src/vdbe.c

2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
....
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
....
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
....
3580
3581
3582
3583
3584
3585
3586


































































3587
3588
3589
3590
3591
3592
3593
    int nField = pC->nField;
    if( pC->pKeyInfo && pC->pKeyInfo->nData ) nField = pC->pKeyInfo->nData;

    rc = sqlite4VdbeCreateDecoder(db, aData, nData, nField, &pCodec);
    if( rc==0 ){
      pDefault = (pOp->p4type==P4_MEM) ? pOp->p4.pMem : 0;
      rc = sqlite4VdbeDecodeValue(pCodec, pOp->p2, pDefault, pDest);
      assert( rc==SQLITE4_OK );
      sqlite4VdbeDestroyDecoder(pCodec);
    }
  }else{
    sqlite4VdbeMemSetNull(pDest);
  }
  UPDATE_MAX_BLOBSIZE(pDest);
  REGISTER_TRACE(pOp->p3, pDest);
................................................................................
    }
  }else{
    assert( pIdx->pKeyInfo->nPK>0 );
    assert( pPk->pKeyInfo->nPK==0 );
    rc = sqlite4KVCursorKey(pIdx->pKVCur, &aKey, &nKey);
    if( rc==SQLITE4_OK ){
      nShort = sqlite4VdbeShortKey(aKey, nKey, 
          pIdx->pKeyInfo->nField - pIdx->pKeyInfo->nPK
      );

      nPkKey = sqlite4VarintLen(pPk->iRoot) + nKey - nShort;
      aPkKey = sqlite4DbMallocRaw(db, nPkKey);

      if( aPkKey ){
        putVarint32(aPkKey, pPk->iRoot);
................................................................................

  pProbe = &aMem[pOp->p3];
  pC = p->apCsr[pOp->p1];
  pOut = (pOp->p4.i==0 ? 0 : &aMem[pOp->p4.i]);
  assert( pOut==0 || (pOut->flags & MEM_Blob) );

  nShort = sqlite4VdbeShortKey((u8 *)pProbe->z, pProbe->n, 
      pC->pKeyInfo->nField - pC->pKeyInfo->nPK
  );
  assert( nShort<=pProbe->n );
  assert( (nShort==pProbe->n)==(pC->pKeyInfo->nPK==0) );

  dir = (pC->pKeyInfo->nPK==0 ? 0 : 1);
  rc = sqlite4KVCursorSeek(pC->pKVCur, (u8 *)pProbe->z, nShort, dir);

................................................................................
  }
  if( rc==SQLITE4_OK && nData>db->aLimit[SQLITE4_LIMIT_LENGTH] ){
    goto too_big;
  }
  sqlite4VdbeMemSetStr(pOut, (const char*)pData, nData, 0, SQLITE4_TRANSIENT,0);
  pOut->enc = SQLITE4_UTF8;  /* In case the blob is ever cast to text */
  UPDATE_MAX_BLOBSIZE(pOut);


































































  break;
}

/* Opcode: Rowid P1 P2 * * *
**
** Store in register P2 an integer which is the key of the table entry that
** P1 is currently point to.







<







 







|







 







|







 







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







2137
2138
2139
2140
2141
2142
2143

2144
2145
2146
2147
2148
2149
2150
....
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
....
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
....
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
    int nField = pC->nField;
    if( pC->pKeyInfo && pC->pKeyInfo->nData ) nField = pC->pKeyInfo->nData;

    rc = sqlite4VdbeCreateDecoder(db, aData, nData, nField, &pCodec);
    if( rc==0 ){
      pDefault = (pOp->p4type==P4_MEM) ? pOp->p4.pMem : 0;
      rc = sqlite4VdbeDecodeValue(pCodec, pOp->p2, pDefault, pDest);

      sqlite4VdbeDestroyDecoder(pCodec);
    }
  }else{
    sqlite4VdbeMemSetNull(pDest);
  }
  UPDATE_MAX_BLOBSIZE(pDest);
  REGISTER_TRACE(pOp->p3, pDest);
................................................................................
    }
  }else{
    assert( pIdx->pKeyInfo->nPK>0 );
    assert( pPk->pKeyInfo->nPK==0 );
    rc = sqlite4KVCursorKey(pIdx->pKVCur, &aKey, &nKey);
    if( rc==SQLITE4_OK ){
      nShort = sqlite4VdbeShortKey(aKey, nKey, 
          pIdx->pKeyInfo->nField - pIdx->pKeyInfo->nPK, 0
      );

      nPkKey = sqlite4VarintLen(pPk->iRoot) + nKey - nShort;
      aPkKey = sqlite4DbMallocRaw(db, nPkKey);

      if( aPkKey ){
        putVarint32(aPkKey, pPk->iRoot);
................................................................................

  pProbe = &aMem[pOp->p3];
  pC = p->apCsr[pOp->p1];
  pOut = (pOp->p4.i==0 ? 0 : &aMem[pOp->p4.i]);
  assert( pOut==0 || (pOut->flags & MEM_Blob) );

  nShort = sqlite4VdbeShortKey((u8 *)pProbe->z, pProbe->n, 
      pC->pKeyInfo->nField - pC->pKeyInfo->nPK, 0
  );
  assert( nShort<=pProbe->n );
  assert( (nShort==pProbe->n)==(pC->pKeyInfo->nPK==0) );

  dir = (pC->pKeyInfo->nPK==0 ? 0 : 1);
  rc = sqlite4KVCursorSeek(pC->pKVCur, (u8 *)pProbe->z, nShort, dir);

................................................................................
  }
  if( rc==SQLITE4_OK && nData>db->aLimit[SQLITE4_LIMIT_LENGTH] ){
    goto too_big;
  }
  sqlite4VdbeMemSetStr(pOut, (const char*)pData, nData, 0, SQLITE4_TRANSIENT,0);
  pOut->enc = SQLITE4_UTF8;  /* In case the blob is ever cast to text */
  UPDATE_MAX_BLOBSIZE(pOut);
  break;
}

/* Opcode: AnalyzeKey P1 P2 P3 P4
**
** P1 is an open cursor that currently points to a valid row. P2 is a 
** register that contains either a NULL value, or an index key. If it is 
** not NULL, this opcode compares the key in register P2 with the key of 
** the row P1 currently points to and determines the number of fields in
** the prefix that the two keys share in common (which may be zero).
** Call this value N. It then increments the integer values stored in
** N consecutive register starting at P3.
**
** Finally, the key belonging to the current row of cursor P1 is copied
** into register P2.
*/
case OP_AnalyzeKey: {
  VdbeCursor *pC;
  const KVByteArray *pNew;
  KVSize nNew;
  Mem *pKey;
  Mem *aIncr;
  int nEq;
  int nTotal;
  int i;
  int nSz;

  pKey = &aMem[pOp->p2];
  aIncr = &aMem[pOp->p3];
  nTotal = pOp->p4.i;
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pC->nullRow==0 );
  assert( pC->pseudoTableReg==0 );
  assert( pC->pKVCur!=0 );
  assert( pOp->p4type==P4_INT32 );

  rc = sqlite4KVCursorKey(pC->pKVCur, &pNew, &nNew);
  if( rc==SQLITE4_OK ){
    assert( pKey->flags & (MEM_Blob|MEM_Null) );
    if( pKey->flags & MEM_Blob ){
      for(i=0; i<nNew && i<pKey->n && pNew[i]==(KVByteArray)pKey->z[i]; i++);

      /* The two keys share i bytes in common. Figure out how many fields
      ** this corresponds to. Store said value in variable nEq. */
      sqlite4VdbeShortKey(pNew, i, LARGEST_INT32, &nEq);

      /* Increment nTotal-nEq registers */
      for(i=nEq; i<nTotal; i++){
        memAboutToChange(p, &aIncr[i]);
        sqlite4VdbeMemIntegerify(&aIncr[i]);
        aIncr[i].u.num = sqlite4_num_add(
            aIncr[i].u.num, sqlite4_num_from_int64(1)
        );
        REGISTER_TRACE(pOp->p1, &aIncr[i]);
      }
    }

    /* Copy the new key into register P2 */
    memAboutToChange(p, pKey);
    sqlite4VdbeMemSetStr(pKey, (const char*)pNew, nNew, 0, SQLITE4_TRANSIENT,0);
    pKey->enc = SQLITE4_UTF8;
    UPDATE_MAX_BLOBSIZE(pKey);
  }


  break;
}

/* Opcode: Rowid P1 P2 * * *
**
** Store in register P2 an integer which is the key of the table entry that
** P1 is currently point to.

Changes to src/vdbeInt.h

380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
  KeyInfo *pKeyInfo,           /* Collating sequence information */
  u8 **pzOut,                  /* Write the resulting key here */
  int *pnOut,                  /* Number of bytes in the key */
  int nExtra                   /* Append extra bytes on end of key */
);
int sqlite4VdbeEncodeIntKey(u8 *aBuf,sqlite4_int64 v);
int sqlite4VdbeDecodeIntKey(const KVByteArray*, KVSize, sqlite4_int64*);
int sqlite4VdbeShortKey(const u8 *, int, int);
int sqlite4MemCompare(Mem*, Mem*, const CollSeq*,int*);
int sqlite4VdbeExec(Vdbe*);
int sqlite4VdbeList(Vdbe*);
int sqlite4VdbeHalt(Vdbe*);
int sqlite4VdbeChangeEncoding(Mem *, int);
int sqlite4VdbeMemTooBig(Mem*);
int sqlite4VdbeMemCopy(Mem*, const Mem*);







|







380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
  KeyInfo *pKeyInfo,           /* Collating sequence information */
  u8 **pzOut,                  /* Write the resulting key here */
  int *pnOut,                  /* Number of bytes in the key */
  int nExtra                   /* Append extra bytes on end of key */
);
int sqlite4VdbeEncodeIntKey(u8 *aBuf,sqlite4_int64 v);
int sqlite4VdbeDecodeIntKey(const KVByteArray*, KVSize, sqlite4_int64*);
int sqlite4VdbeShortKey(const u8 *, int, int, int *);
int sqlite4MemCompare(Mem*, Mem*, const CollSeq*,int*);
int sqlite4VdbeExec(Vdbe*);
int sqlite4VdbeList(Vdbe*);
int sqlite4VdbeHalt(Vdbe*);
int sqlite4VdbeChangeEncoding(Mem *, int);
int sqlite4VdbeMemTooBig(Mem*);
int sqlite4VdbeMemCopy(Mem*, const Mem*);

Changes to src/vdbecodec.c

544
545
546
547
548
549
550
551

552
553
554
555
556
557

558
559
560
561
562
563
564
565
566
567
...
576
577
578
579
580
581
582
583

584
585
586
587
588
589
590
...
608
609
610
611
612
613
614
615



616
617
618
619
620
621
622
** Variables aKey/nKey contain an encoded index key. This function returns
** the length (in bytes) of the key with all but the first nField fields
** removed.
*/
int sqlite4VdbeShortKey(
  const u8 *aKey,                 /* Buffer containing encoded key */
  int nKey,                       /* Size of buffer aKey[] in bytes */
  int nField                      /* Number of fields */

){
  u8 *p = (u8*)aKey;
  u8 *pEnd = (u8*)&aKey[nKey];
  u64 dummy;
  int i;


  p += sqlite4GetVarint64(p, pEnd-p, &dummy);

  for(i=0; i<nField; i++){
    u8 c = *(p++);
    switch( c ){

      case 0x05: case 0xFA:       /* NULL */
      case 0x06: case 0xF9:       /* NaN */
      case 0x07: case 0xF8:       /* -ve infinity */
      case 0x15: case 0xEA:       /* zero */
................................................................................
      case 0xDB:                  /* Text (descending index) */
      case 0xDA:                  /* Blob (descending index) */
        while( (0xFF!=*(p++)) );
        break;

      case 0x26:                  /* Blob-final (ascending) */
      case 0xD9:                  /* Blob-final (descending) */
        return nKey;


      case 0x22: case 0xDD:       /* Large positive number */
      case 0x14: case 0xEB:       /* Small negative number */
      case 0x16: case 0xE9:       /* Small positive number */
      case 0x08: case 0xF7: {     /* Large negative number */
        u8 d;                     /* Value of byte following "c" */

................................................................................
        if( c<0x15 || (c>0xDC && c<0xEA) ){
          while( !((*p++) & 0x01) );
        }else{
          while( ((*p++) & 0x01) );
        }
        break;
    }
  }




  return (p - aKey);
}

/*
** Generate a database key from one or more data values.
**







|
>






>


|







 







|
>







 







|
>
>
>







544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
...
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
...
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
** Variables aKey/nKey contain an encoded index key. This function returns
** the length (in bytes) of the key with all but the first nField fields
** removed.
*/
int sqlite4VdbeShortKey(
  const u8 *aKey,                 /* Buffer containing encoded key */
  int nKey,                       /* Size of buffer aKey[] in bytes */
  int nField,                     /* Number of fields */
  int *pnOut                      /* Number of complete fields read (or NULL) */
){
  u8 *p = (u8*)aKey;
  u8 *pEnd = (u8*)&aKey[nKey];
  u64 dummy;
  int i;

  /* Skip over the "root page" number at the start of the key */
  p += sqlite4GetVarint64(p, pEnd-p, &dummy);

  for(i=0; i<nField && p<pEnd; i++){
    u8 c = *(p++);
    switch( c ){

      case 0x05: case 0xFA:       /* NULL */
      case 0x06: case 0xF9:       /* NaN */
      case 0x07: case 0xF8:       /* -ve infinity */
      case 0x15: case 0xEA:       /* zero */
................................................................................
      case 0xDB:                  /* Text (descending index) */
      case 0xDA:                  /* Blob (descending index) */
        while( (0xFF!=*(p++)) );
        break;

      case 0x26:                  /* Blob-final (ascending) */
      case 0xD9:                  /* Blob-final (descending) */
        p = pEnd;
        break;

      case 0x22: case 0xDD:       /* Large positive number */
      case 0x14: case 0xEB:       /* Small negative number */
      case 0x16: case 0xE9:       /* Small positive number */
      case 0x08: case 0xF7: {     /* Large negative number */
        u8 d;                     /* Value of byte following "c" */

................................................................................
        if( c<0x15 || (c>0xDC && c<0xEA) ){
          while( !((*p++) & 0x01) );
        }else{
          while( ((*p++) & 0x01) );
        }
        break;
    }

    if( p>pEnd ) break;
  }
  if( pnOut ) *pnOut = i;

  return (p - aKey);
}

/*
** Generate a database key from one or more data values.
**

Changes to test/analyze.test

139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
...
201
202
203
204
205
206
207
208
209
210
211
212
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
...
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
...
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
do_test analyze-3.1 {
  execsql {
    INSERT INTO t1 VALUES(1,2);
    INSERT INTO t1 VALUES(1,3);
    ANALYZE main.t1;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t1i1 {2 2} t1i2 {2 1} t1i3 {2 2 1}}
do_test analyze-3.2 {
  execsql {
    INSERT INTO t1 VALUES(1,4);
    INSERT INTO t1 VALUES(1,5);
    ANALYZE t1;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t1i1 {4 4} t1i2 {4 1} t1i3 {4 4 1}}
do_test analyze-3.3 {
  execsql {
    INSERT INTO t1 VALUES(2,5);
    ANALYZE main;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t1i1 {5 3} t1i2 {5 2} t1i3 {5 3 1}}
do_test analyze-3.4 {
  execsql {
    CREATE TABLE t2 AS SELECT * FROM t1;
    CREATE INDEX t2i1 ON t2(a);
    CREATE INDEX t2i2 ON t2(b);
    CREATE INDEX t2i3 ON t2(a,b);
    ANALYZE;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t1i1 {5 3} t1i2 {5 2} t1i3 {5 3 1} t2i1 {5 3} t2i2 {5 2} t2i3 {5 3 1}}
do_test analyze-3.5 {
  execsql {
    DROP INDEX t2i3;
    ANALYZE t1;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t1i1 {5 3} t1i2 {5 2} t1i3 {5 3 1} t2i1 {5 3} t2i2 {5 2}}
do_test analyze-3.6 {
  execsql {
    ANALYZE t2;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t1i1 {5 3} t1i2 {5 2} t1i3 {5 3 1} t2i1 {5 3} t2i2 {5 2}}
do_test analyze-3.7 {
  execsql {
    DROP INDEX t2i2;
    ANALYZE t2;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t1i1 {5 3} t1i2 {5 2} t1i3 {5 3 1} t2i1 {5 3}}
do_test analyze-3.8 {
  execsql {
    CREATE TABLE t3 AS SELECT a, b, rowid AS c, 'hi' AS d FROM t1;
    CREATE INDEX t3i1 ON t3(a);
    CREATE INDEX t3i2 ON t3(a,b,c,d);
    CREATE INDEX t3i3 ON t3(d,b,c,a);
    DROP TABLE t1;
................................................................................
  }
} {}
do_test analyze-3.9 {
  execsql {
    ANALYZE;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t3i1 {5 3} t3i2 {5 3 1 1 1} t3i3 {5 5 2 1 1}}

do_test analyze-3.10 {
  execsql {
    CREATE TABLE [silly " name](a, b, c);
    CREATE INDEX 'foolish '' name' ON [silly " name](a, b);
    CREATE INDEX 'another foolish '' name' ON [silly " name](c);
    INSERT INTO [silly " name] VALUES(1, 2, 3);
    INSERT INTO [silly " name] VALUES(4, 5, 6);
    ANALYZE;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {{another foolish ' name} {2 1} {foolish ' name} {2 1 1} t3i1 {5 3} t3i2 {5 3 1 1 1} t3i3 {5 5 2 1 1}}
do_test analyze-3.11 {
  execsql {
    DROP INDEX "foolish ' name";
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {{another foolish ' name} {2 1} t3i1 {5 3} t3i2 {5 3 1 1 1} t3i3 {5 5 2 1 1}}
do_test analyze-3.11 {
  execsql {
    DROP TABLE "silly "" name";
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t3i1 {5 3} t3i2 {5 3 1 1 1} t3i3 {5 5 2 1 1}}

# Try corrupting the sqlite_stat1 table and make sure the
# database is still able to function.
#
do_test analyze-4.0 {
  sqlite4 db2 test.db
  db2 eval {
................................................................................
  db2 close
  db close
  sqlite4 db test.db
  execsql {
    ANALYZE;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t3i1 {5 3} t3i2 {5 3 1 1 1} t3i3 {5 5 2 1 1} t4i1 {5 3} t4i2 {5 2}}
do_test analyze-4.1 {
  execsql {
    PRAGMA writable_schema=on;
    INSERT INTO sqlite_stat1 VALUES(null,null,null);
    PRAGMA writable_schema=off;
  }
  db close
................................................................................
    INSERT INTO t3 SELECT a+32, b+32, c+32, d+32 FROM t3;
    INSERT INTO t3 SELECT a+64, b+64, c+64, d+64 FROM t3;
    INSERT INTO t4 SELECT a, b, c FROM t3;
    ANALYZE;
    SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1;
    SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
  }
} {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4}
ifcapable stat3 {
  do_test analyze-5.1 {
    execsql {
      SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1;
      SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1;
    }
  } {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4}
}
do_test analyze-5.2 {
  execsql {
    DROP INDEX t3i2;
    SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1;
    SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
  }
} {t3i1 t3i3 t4i1 t4i2 t3 t4}
ifcapable stat3 {
  do_test analyze-5.3 {
    execsql {
      SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1;
      SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1;
    }
  } {t3i1 t3i3 t4i1 t4i2 t3 t4}
}
do_test analyze-5.4 {
  execsql {
    DROP TABLE t3;
    SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1;
    SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
  }
} {t4i1 t4i2 t4}
ifcapable stat3 {
  do_test analyze-5.5 {
    execsql {
      SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1;
      SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1;
    }
  } {t4i1 t4i2 t4}







|







|






|









|






|





|






|







 







|











|





|





|







 







|







 







|






|







|






|







|







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
...
201
202
203
204
205
206
207
208
209
210
211
212
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
...
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
...
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
do_test analyze-3.1 {
  execsql {
    INSERT INTO t1 VALUES(1,2);
    INSERT INTO t1 VALUES(1,3);
    ANALYZE main.t1;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t1 {2 1} t1i1 {2 2} t1i2 {2 1} t1i3 {2 2 1}}
do_test analyze-3.2 {
  execsql {
    INSERT INTO t1 VALUES(1,4);
    INSERT INTO t1 VALUES(1,5);
    ANALYZE t1;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t1 {4 1} t1i1 {4 4} t1i2 {4 1} t1i3 {4 4 1}}
do_test analyze-3.3 {
  execsql {
    INSERT INTO t1 VALUES(2,5);
    ANALYZE main;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t1 {5 1} t1i1 {5 3} t1i2 {5 2} t1i3 {5 3 1}}
do_test analyze-3.4 {
  execsql {
    CREATE TABLE t2 AS SELECT * FROM t1;
    CREATE INDEX t2i1 ON t2(a);
    CREATE INDEX t2i2 ON t2(b);
    CREATE INDEX t2i3 ON t2(a,b);
    ANALYZE;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t1 {5 1} t1i1 {5 3} t1i2 {5 2} t1i3 {5 3 1} t2 {5 1} t2i1 {5 3} t2i2 {5 2} t2i3 {5 3 1}}
do_test analyze-3.5 {
  execsql {
    DROP INDEX t2i3;
    ANALYZE t1;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t1 {5 1} t1i1 {5 3} t1i2 {5 2} t1i3 {5 3 1} t2 {5 1} t2i1 {5 3} t2i2 {5 2}}
do_test analyze-3.6 {
  execsql {
    ANALYZE t2;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t1 {5 1} t1i1 {5 3} t1i2 {5 2} t1i3 {5 3 1} t2 {5 1} t2i1 {5 3} t2i2 {5 2}}
do_test analyze-3.7 {
  execsql {
    DROP INDEX t2i2;
    ANALYZE t2;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t1 {5 1} t1i1 {5 3} t1i2 {5 2} t1i3 {5 3 1} t2 {5 1} t2i1 {5 3}}
do_test analyze-3.8 {
  execsql {
    CREATE TABLE t3 AS SELECT a, b, rowid AS c, 'hi' AS d FROM t1;
    CREATE INDEX t3i1 ON t3(a);
    CREATE INDEX t3i2 ON t3(a,b,c,d);
    CREATE INDEX t3i3 ON t3(d,b,c,a);
    DROP TABLE t1;
................................................................................
  }
} {}
do_test analyze-3.9 {
  execsql {
    ANALYZE;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t3 {5 1} t3i1 {5 3} t3i2 {5 3 1 1 1} t3i3 {5 5 2 1 1}}

do_test analyze-3.10 {
  execsql {
    CREATE TABLE [silly " name](a, b, c);
    CREATE INDEX 'foolish '' name' ON [silly " name](a, b);
    CREATE INDEX 'another foolish '' name' ON [silly " name](c);
    INSERT INTO [silly " name] VALUES(1, 2, 3);
    INSERT INTO [silly " name] VALUES(4, 5, 6);
    ANALYZE;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {{another foolish ' name} {2 1} {foolish ' name} {2 1 1} {silly " name} {2 1} t3 {5 1} t3i1 {5 3} t3i2 {5 3 1 1 1} t3i3 {5 5 2 1 1}}
do_test analyze-3.11 {
  execsql {
    DROP INDEX "foolish ' name";
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {{another foolish ' name} {2 1} {silly " name} {2 1} t3 {5 1} t3i1 {5 3} t3i2 {5 3 1 1 1} t3i3 {5 5 2 1 1}}
do_test analyze-3.11 {
  execsql {
    DROP TABLE "silly "" name";
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t3 {5 1} t3i1 {5 3} t3i2 {5 3 1 1 1} t3i3 {5 5 2 1 1}}

# Try corrupting the sqlite_stat1 table and make sure the
# database is still able to function.
#
do_test analyze-4.0 {
  sqlite4 db2 test.db
  db2 eval {
................................................................................
  db2 close
  db close
  sqlite4 db test.db
  execsql {
    ANALYZE;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
  }
} {t3 {5 1} t3i1 {5 3} t3i2 {5 3 1 1 1} t3i3 {5 5 2 1 1} t4 {5 1} t4i1 {5 3} t4i2 {5 2}}
do_test analyze-4.1 {
  execsql {
    PRAGMA writable_schema=on;
    INSERT INTO sqlite_stat1 VALUES(null,null,null);
    PRAGMA writable_schema=off;
  }
  db close
................................................................................
    INSERT INTO t3 SELECT a+32, b+32, c+32, d+32 FROM t3;
    INSERT INTO t3 SELECT a+64, b+64, c+64, d+64 FROM t3;
    INSERT INTO t4 SELECT a, b, c FROM t3;
    ANALYZE;
    SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1;
    SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
  }
} {t3 t3i1 t3i2 t3i3 t4 t4i1 t4i2 t3 t4}
ifcapable stat3 {
  do_test analyze-5.1 {
    execsql {
      SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1;
      SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1;
    }
  } {t3 t3i1 t3i2 t3i3 t4 t4i1 t4i2 t3 t4}
}
do_test analyze-5.2 {
  execsql {
    DROP INDEX t3i2;
    SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1;
    SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
  }
} {t3 t3i1 t3i3 t4 t4i1 t4i2 t3 t4}
ifcapable stat3 {
  do_test analyze-5.3 {
    execsql {
      SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1;
      SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1;
    }
  } {t3i1 t3i3 t4 t4i1 t4i2 t3 t4}
}
do_test analyze-5.4 {
  execsql {
    DROP TABLE t3;
    SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1;
    SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
  }
} {t4 t4i1 t4i2 t4}
ifcapable stat3 {
  do_test analyze-5.5 {
    execsql {
      SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1;
      SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1;
    }
  } {t4i1 t4i2 t4}

Changes to test/auth.test

1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
....
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
    }
    set ::authargs
  } {t4 {} main {} t2 {} main {}}
  do_test auth-1.295 {
    execsql {
      SELECT count(*) FROM sqlite_stat1;
    }
  } 3
  proc auth {code args} {
    if {$code=="SQLITE4_ANALYZE"} {
      set ::authargs [concat $::authargs $args]
      return SQLITE4_DENY
    }
    return SQLITE4_OK
  }
................................................................................
      ANALYZE;
    }
  } {1 {not authorized}}
  do_test auth-1.297 {
    execsql {
      SELECT count(*) FROM sqlite_stat1;
    }
  } 3
} ;# ifcapable analyze


# Authorization for ALTER TABLE ADD COLUMN.
# These tests are omitted if the library
# was built without ALTER TABLE support.
ifcapable {altertable} {







|







 







|







1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
....
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
    }
    set ::authargs
  } {t4 {} main {} t2 {} main {}}
  do_test auth-1.295 {
    execsql {
      SELECT count(*) FROM sqlite_stat1;
    }
  } 4
  proc auth {code args} {
    if {$code=="SQLITE4_ANALYZE"} {
      set ::authargs [concat $::authargs $args]
      return SQLITE4_DENY
    }
    return SQLITE4_OK
  }
................................................................................
      ANALYZE;
    }
  } {1 {not authorized}}
  do_test auth-1.297 {
    execsql {
      SELECT count(*) FROM sqlite_stat1;
    }
  } 4
} ;# ifcapable analyze


# Authorization for ALTER TABLE ADD COLUMN.
# These tests are omitted if the library
# was built without ALTER TABLE support.
ifcapable {altertable} {

Changes to test/permutations.test

137
138
139
140
141
142
143

144
145
146
147
148
149
150
  lsm1.test lsm2.test lsm3.test lsm4.test lsm5.test
  csr1.test
  ckpt1.test
  mc1.test
  fts5expr1.test fts5query1.test fts5rnd1.test fts5create.test
  fts5snippet.test


  auth.test auth2.test auth3.test auth4.test
  aggerror.test
  attach.test
  autoindex1.test
  badutf.test
  between.test
  bigrow.test







>







137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
  lsm1.test lsm2.test lsm3.test lsm4.test lsm5.test
  csr1.test
  ckpt1.test
  mc1.test
  fts5expr1.test fts5query1.test fts5rnd1.test fts5create.test
  fts5snippet.test

  analyze.test
  auth.test auth2.test auth3.test auth4.test
  aggerror.test
  attach.test
  autoindex1.test
  badutf.test
  between.test
  bigrow.test