/ Check-in [74a0ca1f]
Login

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

Overview
Comment:Merge recent trunk enhancements.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | est_count_pragma
Files: files | file ages | folders
SHA1: 74a0ca1f152d6d8454787557c6e990efe0e47a50
User & Date: drh 2016-12-16 15:57:40
Context
2016-12-16
21:02
Fix a potential memory leak following an OOM error in the pragma processing. check-in: 396ab8f8 user: drh tags: est_count_pragma
16:49
Experimental merge of the est_count_pragma and the pragma-as-vtab branches. Closed-Leaf check-in: 4b73ee33 user: drh tags: est-count-pragma-vtab
15:57
Merge recent trunk enhancements. check-in: 74a0ca1f user: drh tags: est_count_pragma
15:05
Fix a problem causing the planner to generate sub-optimal plans for some queries that use recursive WITH sub-queries with LIMIT clauses. check-in: 053a149c user: dan tags: trunk
2016-12-12
12:58
Merge recent enhancements from trunk. check-in: dc006e08 user: drh tags: est_count_pragma
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Makefile.in.

1105
1106
1107
1108
1109
1110
1111




1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129

fastfuzztest:	fuzzcheck$(TEXE) $(FUZZDATA)
	./fuzzcheck$(TEXE) --limit-mem 100M $(FUZZDATA)

valgrindfuzz:	fuzzcheck$(TEXT) $(FUZZDATA)
	valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)






# Minimal testing that runs in less than 3 minutes
#
quicktest:	./testfixture$(TEXE)
	./testfixture$(TEXE) $(TOP)/test/extraquick.test $(TESTOPTS)

# This is the common case.  Run many tests that do not take too long,
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
#
test:	$(TESTPROGS) sourcetest fastfuzztest
	./testfixture$(TEXE) $(TOP)/test/veryquick.test $(TESTOPTS)

# Run a test using valgrind.  This can take a really long time
# because valgrind is so much slower than a native machine.
#
valgrindtest:	$(TESTPROGS) valgrindfuzz
	OMIT_MISUSE=1 valgrind -v ./testfixture$(TEXE) $(TOP)/test/permutations.test valgrind $(TESTOPTS)








>
>
>
>









|
<







1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125

1126
1127
1128
1129
1130
1131
1132

fastfuzztest:	fuzzcheck$(TEXE) $(FUZZDATA)
	./fuzzcheck$(TEXE) --limit-mem 100M $(FUZZDATA)

valgrindfuzz:	fuzzcheck$(TEXT) $(FUZZDATA)
	valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)

# The veryquick.test TCL tests.
#
tcltest:	./testfixture$(TEXE)
	./testfixture$(TEXE) $(TOP)/test/veryquick.test $(TESTOPTS)

# Minimal testing that runs in less than 3 minutes
#
quicktest:	./testfixture$(TEXE)
	./testfixture$(TEXE) $(TOP)/test/extraquick.test $(TESTOPTS)

# This is the common case.  Run many tests that do not take too long,
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
#
test:	fastfuzztest sourcetest $(TESTPROGS) tcltest


# Run a test using valgrind.  This can take a really long time
# because valgrind is so much slower than a native machine.
#
valgrindtest:	$(TESTPROGS) valgrindfuzz
	OMIT_MISUSE=1 valgrind -v ./testfixture$(TEXE) $(TOP)/test/permutations.test valgrind $(TESTOPTS)

Changes to main.mk.

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

fastfuzztest:	fuzzcheck$(EXE) $(FUZZDATA)
	./fuzzcheck$(EXE) --limit-mem 100M $(FUZZDATA)

valgrindfuzz:	fuzzcheck$(EXE) $(FUZZDATA)
	valgrind ./fuzzcheck$(EXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)






# A very quick test using only testfixture and omitting all the slower
# tests.  Designed to run in under 3 minutes on a workstation.
#
quicktest:	./testfixture$(EXE)
	./testfixture$(EXE) $(TOP)/test/extraquick.test $(TESTOPTS)

# The default test case.  Runs most of the faster standard TCL tests,
# and fuzz tests, and sqlite3_analyzer and sqldiff tests.
#
test:	$(TESTPROGS) sourcetest fastfuzztest
	./testfixture$(EXE) $(TOP)/test/veryquick.test $(TESTOPTS)

# Run a test using valgrind.  This can take a really long time
# because valgrind is so much slower than a native machine.
#
valgrindtest:	$(TESTPROGS) valgrindfuzz
	OMIT_MISUSE=1 valgrind -v \
	./testfixture$(EXE) $(TOP)/test/permutations.test valgrind $(TESTOPTS)







>
>
>
>
>








|
<
<







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

fastfuzztest:	fuzzcheck$(EXE) $(FUZZDATA)
	./fuzzcheck$(EXE) --limit-mem 100M $(FUZZDATA)

valgrindfuzz:	fuzzcheck$(EXE) $(FUZZDATA)
	valgrind ./fuzzcheck$(EXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)

# The veryquick.test TCL tests.
#
tcltest:	./testfixture$(EXE)
	./testfixture$(EXE) $(TOP)/test/veryquick.test $(TESTOPTS)

# A very quick test using only testfixture and omitting all the slower
# tests.  Designed to run in under 3 minutes on a workstation.
#
quicktest:	./testfixture$(EXE)
	./testfixture$(EXE) $(TOP)/test/extraquick.test $(TESTOPTS)

# The default test case.  Runs most of the faster standard TCL tests,
# and fuzz tests, and sqlite3_analyzer and sqldiff tests.
test:	fastfuzztest sourcetest $(TESTPROGS) tcltest



# Run a test using valgrind.  This can take a really long time
# because valgrind is so much slower than a native machine.
#
valgrindtest:	$(TESTPROGS) valgrindfuzz
	OMIT_MISUSE=1 valgrind -v \
	./testfixture$(EXE) $(TOP)/test/permutations.test valgrind $(TESTOPTS)

Changes to src/alter.c.

500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
...
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
...
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
...
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
...
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
    /* If foreign-key support is enabled, rewrite the CREATE TABLE 
    ** statements corresponding to all child tables of foreign key constraints
    ** for which the renamed table is the parent table.  */
    if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){
      sqlite3NestedParse(pParse, 
          "UPDATE \"%w\".%s SET "
              "sql = sqlite_rename_parent(sql, %Q, %Q) "
              "WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere);
      sqlite3DbFree(db, zWhere);
    }
  }
#endif

  /* Modify the sqlite_master table to use the new table name. */
  sqlite3NestedParse(pParse,
................................................................................
          "name = CASE "
            "WHEN type='table' THEN %Q "
            "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN "
             "'sqlite_autoindex_' || %Q || substr(name,%d+18) "
            "ELSE name END "
      "WHERE tbl_name=%Q COLLATE nocase AND "
          "(type='table' OR type='index' OR type='trigger');", 
      zDb, SCHEMA_TABLE(iDb), zName, zName, zName, 
#ifndef SQLITE_OMIT_TRIGGER
      zName,
#endif
      zName, nTabName, zTabName
  );

#ifndef SQLITE_OMIT_AUTOINCREMENT
................................................................................
      *zEnd-- = '\0';
    }
    db->flags |= SQLITE_PreferBuiltin;
    sqlite3NestedParse(pParse, 
        "UPDATE \"%w\".%s SET "
          "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) "
        "WHERE type = 'table' AND name = %Q", 
      zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1,
      zTab
    );
    sqlite3DbFree(db, zCol);
    db->flags = savedDbFlags;
  }

  /* Make sure the schema version is at least 3.  But do not upgrade
................................................................................
  ** prefix, we insure that the name will not collide with an existing
  ** table because user table are not allowed to have the "sqlite_"
  ** prefix on their name.
  */
  pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table));
  if( !pNew ) goto exit_begin_add_column;
  pParse->pNewTable = pNew;
  pNew->nRef = 1;
  pNew->nCol = pTab->nCol;
  assert( pNew->nCol>0 );
  nAlloc = (((pNew->nCol-1)/8)*8)+8;
  assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
  pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc);
  pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName);
  if( !pNew->aCol || !pNew->zName ){
................................................................................
    Column *pCol = &pNew->aCol[i];
    pCol->zName = sqlite3DbStrDup(db, pCol->zName);
    pCol->zColl = 0;
    pCol->pDflt = 0;
  }
  pNew->pSchema = db->aDb[iDb].pSchema;
  pNew->addColOffset = pTab->addColOffset;
  pNew->nRef = 1;

  /* Begin a transaction and increment the schema cookie.  */
  sqlite3BeginWriteOperation(pParse, 0, iDb);
  v = sqlite3GetVdbe(pParse);
  if( !v ) goto exit_begin_add_column;
  sqlite3ChangeCookie(pParse, iDb);

exit_begin_add_column:
  sqlite3SrcListDelete(db, pSrc);
  return;
}
#endif  /* SQLITE_ALTER_TABLE */







|







 







|







 







|







 







|







 







|












500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
...
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
...
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
...
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
...
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
    /* If foreign-key support is enabled, rewrite the CREATE TABLE 
    ** statements corresponding to all child tables of foreign key constraints
    ** for which the renamed table is the parent table.  */
    if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){
      sqlite3NestedParse(pParse, 
          "UPDATE \"%w\".%s SET "
              "sql = sqlite_rename_parent(sql, %Q, %Q) "
              "WHERE %s;", zDb, MASTER_NAME, zTabName, zName, zWhere);
      sqlite3DbFree(db, zWhere);
    }
  }
#endif

  /* Modify the sqlite_master table to use the new table name. */
  sqlite3NestedParse(pParse,
................................................................................
          "name = CASE "
            "WHEN type='table' THEN %Q "
            "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN "
             "'sqlite_autoindex_' || %Q || substr(name,%d+18) "
            "ELSE name END "
      "WHERE tbl_name=%Q COLLATE nocase AND "
          "(type='table' OR type='index' OR type='trigger');", 
      zDb, MASTER_NAME, zName, zName, zName, 
#ifndef SQLITE_OMIT_TRIGGER
      zName,
#endif
      zName, nTabName, zTabName
  );

#ifndef SQLITE_OMIT_AUTOINCREMENT
................................................................................
      *zEnd-- = '\0';
    }
    db->flags |= SQLITE_PreferBuiltin;
    sqlite3NestedParse(pParse, 
        "UPDATE \"%w\".%s SET "
          "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) "
        "WHERE type = 'table' AND name = %Q", 
      zDb, MASTER_NAME, pNew->addColOffset, zCol, pNew->addColOffset+1,
      zTab
    );
    sqlite3DbFree(db, zCol);
    db->flags = savedDbFlags;
  }

  /* Make sure the schema version is at least 3.  But do not upgrade
................................................................................
  ** prefix, we insure that the name will not collide with an existing
  ** table because user table are not allowed to have the "sqlite_"
  ** prefix on their name.
  */
  pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table));
  if( !pNew ) goto exit_begin_add_column;
  pParse->pNewTable = pNew;
  pNew->nTabRef = 1;
  pNew->nCol = pTab->nCol;
  assert( pNew->nCol>0 );
  nAlloc = (((pNew->nCol-1)/8)*8)+8;
  assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
  pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc);
  pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName);
  if( !pNew->aCol || !pNew->zName ){
................................................................................
    Column *pCol = &pNew->aCol[i];
    pCol->zName = sqlite3DbStrDup(db, pCol->zName);
    pCol->zColl = 0;
    pCol->pDflt = 0;
  }
  pNew->pSchema = db->aDb[iDb].pSchema;
  pNew->addColOffset = pTab->addColOffset;
  pNew->nTabRef = 1;

  /* Begin a transaction and increment the schema cookie.  */
  sqlite3BeginWriteOperation(pParse, 0, iDb);
  v = sqlite3GetVdbe(pParse);
  if( !v ) goto exit_begin_add_column;
  sqlite3ChangeCookie(pParse, iDb);

exit_begin_add_column:
  sqlite3SrcListDelete(db, pSrc);
  return;
}
#endif  /* SQLITE_ALTER_TABLE */

Changes to src/btree.c.

1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
....
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
....
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
....
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
....
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
....
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
  assert( pPage->pBt->db!=0 );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
  assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
  assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );

  if( !pPage->isInit ){
    u32 pc;            /* Address of a freeblock within pPage->aData[] */
    u8 hdr;            /* Offset to beginning of page header */
    u8 *data;          /* Equal to pPage->aData */
    BtShared *pBt;        /* The main btree structure */
    int usableSize;    /* Amount of usable space on each page */
    u16 cellOffset;    /* Offset from start of page to first cell pointer */
    int nFree;         /* Number of unused bytes on the page */
    int top;           /* First byte of the cell content area */
................................................................................
        nFree = nFree + size;
        if( next<=pc+size+3 ) break;
        pc = next;
      }
      if( next>0 ){
        return SQLITE_CORRUPT_BKPT;  /* Freeblock not in ascending order */
      }
      if( pc+size>usableSize ){
        return SQLITE_CORRUPT_BKPT;  /* Last freeblock extends past page end */
      }
    }

    /* At this point, nFree contains the sum of the offset to the start
    ** of the cell-content area plus the number of free bytes within
    ** the cell-content area. If this is greater than the usable-size
................................................................................
** map entries for the overflow pages as well.
*/
static int setChildPtrmaps(MemPage *pPage){
  int i;                             /* Counter variable */
  int nCell;                         /* Number of cells in page pPage */
  int rc;                            /* Return code */
  BtShared *pBt = pPage->pBt;
  u8 isInitOrig = pPage->isInit;
  Pgno pgno = pPage->pgno;

  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  rc = btreeInitPage(pPage);
  if( rc!=SQLITE_OK ){
    goto set_child_ptrmaps_out;
  }
  nCell = pPage->nCell;

  for(i=0; i<nCell; i++){
    u8 *pCell = findCell(pPage, i);

    ptrmapPutOvflPtr(pPage, pCell, &rc);

................................................................................
  }

  if( !pPage->leaf ){
    Pgno childPgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
    ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc);
  }

set_child_ptrmaps_out:
  pPage->isInit = isInitOrig;
  return rc;
}

/*
** Somewhere on pPage is a pointer to page iFrom.  Modify this pointer so
** that it points to iTo. Parameter eType describes the type of pointer to
** be modified, as  follows:
................................................................................
  if( eType==PTRMAP_OVERFLOW2 ){
    /* The pointer is always the first 4 bytes of the page in this case.  */
    if( get4byte(pPage->aData)!=iFrom ){
      return SQLITE_CORRUPT_BKPT;
    }
    put4byte(pPage->aData, iTo);
  }else{
    u8 isInitOrig = pPage->isInit;
    int i;
    int nCell;
    int rc;

    rc = btreeInitPage(pPage);
    if( rc ) return rc;
    nCell = pPage->nCell;
................................................................................
    if( i==nCell ){
      if( eType!=PTRMAP_BTREE || 
          get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
        return SQLITE_CORRUPT_BKPT;
      }
      put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);
    }

    pPage->isInit = isInitOrig;
  }
  return SQLITE_OK;
}


/*
** Move the open database page pDbPage to location iFreePage in the 







|







 







|







 







<




|
<
<







 







<
<







 







<







 







<
<







1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
....
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
....
3292
3293
3294
3295
3296
3297
3298

3299
3300
3301
3302
3303


3304
3305
3306
3307
3308
3309
3310
....
3315
3316
3317
3318
3319
3320
3321


3322
3323
3324
3325
3326
3327
3328
....
3342
3343
3344
3345
3346
3347
3348

3349
3350
3351
3352
3353
3354
3355
....
3377
3378
3379
3380
3381
3382
3383


3384
3385
3386
3387
3388
3389
3390
  assert( pPage->pBt->db!=0 );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
  assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
  assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );

  if( !pPage->isInit ){
    int pc;            /* Address of a freeblock within pPage->aData[] */
    u8 hdr;            /* Offset to beginning of page header */
    u8 *data;          /* Equal to pPage->aData */
    BtShared *pBt;        /* The main btree structure */
    int usableSize;    /* Amount of usable space on each page */
    u16 cellOffset;    /* Offset from start of page to first cell pointer */
    int nFree;         /* Number of unused bytes on the page */
    int top;           /* First byte of the cell content area */
................................................................................
        nFree = nFree + size;
        if( next<=pc+size+3 ) break;
        pc = next;
      }
      if( next>0 ){
        return SQLITE_CORRUPT_BKPT;  /* Freeblock not in ascending order */
      }
      if( pc+size>(unsigned int)usableSize ){
        return SQLITE_CORRUPT_BKPT;  /* Last freeblock extends past page end */
      }
    }

    /* At this point, nFree contains the sum of the offset to the start
    ** of the cell-content area plus the number of free bytes within
    ** the cell-content area. If this is greater than the usable-size
................................................................................
** map entries for the overflow pages as well.
*/
static int setChildPtrmaps(MemPage *pPage){
  int i;                             /* Counter variable */
  int nCell;                         /* Number of cells in page pPage */
  int rc;                            /* Return code */
  BtShared *pBt = pPage->pBt;

  Pgno pgno = pPage->pgno;

  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  rc = btreeInitPage(pPage);
  if( rc!=SQLITE_OK ) return rc;


  nCell = pPage->nCell;

  for(i=0; i<nCell; i++){
    u8 *pCell = findCell(pPage, i);

    ptrmapPutOvflPtr(pPage, pCell, &rc);

................................................................................
  }

  if( !pPage->leaf ){
    Pgno childPgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
    ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc);
  }



  return rc;
}

/*
** Somewhere on pPage is a pointer to page iFrom.  Modify this pointer so
** that it points to iTo. Parameter eType describes the type of pointer to
** be modified, as  follows:
................................................................................
  if( eType==PTRMAP_OVERFLOW2 ){
    /* The pointer is always the first 4 bytes of the page in this case.  */
    if( get4byte(pPage->aData)!=iFrom ){
      return SQLITE_CORRUPT_BKPT;
    }
    put4byte(pPage->aData, iTo);
  }else{

    int i;
    int nCell;
    int rc;

    rc = btreeInitPage(pPage);
    if( rc ) return rc;
    nCell = pPage->nCell;
................................................................................
    if( i==nCell ){
      if( eType!=PTRMAP_BTREE || 
          get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
        return SQLITE_CORRUPT_BKPT;
      }
      put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);
    }


  }
  return SQLITE_OK;
}


/*
** Move the open database page pDbPage to location iFreePage in the 

Changes to src/build.c.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
..
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
..
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
...
304
305
306
307
308
309
310

311
312
313
314
315
316
317
318







319
320
321
322
323
324
325
326
...
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
...
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
...
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
....
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
....
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
....
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
....
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
....
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
....
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
....
3745
3746
3747
3748
3749
3750
3751
3752
3753



3754

3755
3756
3757
3758
3759
3760
3761

#ifndef SQLITE_OMIT_SHARED_CACHE
/*
** The TableLock structure is only used by the sqlite3TableLock() and
** codeTableLocks() functions.
*/
struct TableLock {
  int iDb;             /* The database containing the table to be locked */
  int iTab;            /* The root page of the table to be locked */
  u8 isWriteLock;      /* True for write lock.  False for a read lock */
  const char *zName;   /* Name of the table */
};

/*
** Record the fact that we want to lock a table at run-time.  
**
** The table to be locked has root page iTab and is found in database iDb.
** A read or a write lock can be taken depending on isWritelock.
................................................................................
  pToplevel->aTableLock =
      sqlite3DbReallocOrFree(pToplevel->db, pToplevel->aTableLock, nBytes);
  if( pToplevel->aTableLock ){
    p = &pToplevel->aTableLock[pToplevel->nTableLock++];
    p->iDb = iDb;
    p->iTab = iTab;
    p->isWriteLock = isWriteLock;
    p->zName = zName;
  }else{
    pToplevel->nTableLock = 0;
    sqlite3OomFault(pToplevel->db);
  }
}

/*
................................................................................
  pVdbe = sqlite3GetVdbe(pParse);
  assert( pVdbe!=0 ); /* sqlite3GetVdbe cannot fail: VDBE already allocated */

  for(i=0; i<pParse->nTableLock; i++){
    TableLock *p = &pParse->aTableLock[i];
    int p1 = p->iDb;
    sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock,
                      p->zName, P4_STATIC);
  }
}
#else
  #define codeTableLocks(x)
#endif

/*
................................................................................
#if SQLITE_USER_AUTHENTICATION
  /* Only the admin user is allowed to know that the sqlite_user table
  ** exists */
  if( db->auth.authLevel<UAUTH_Admin && sqlite3UserAuthTable(zName)!=0 ){
    return 0;
  }
#endif

  for(i=OMIT_TEMPDB; i<db->nDb; i++){
    int j = (i<2) ? i^1 : i;   /* Search TEMP before MAIN */
    if( zDatabase==0 || sqlite3StrICmp(zDatabase, db->aDb[j].zDbSName)==0 ){
      assert( sqlite3SchemaMutexHeld(db, j, 0) );
      p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
      if( p ) break;
    }
  }







  return p;
}

/*
** Locate the in-memory structure that describes a particular database
** table given the name of that table and (optionally) the name of the
** database containing the table.  Return NULL if not found.  Also leave an
** error message in pParse->zErrMsg.
................................................................................

  /* Verify that no lookaside memory was used by schema tables */
  assert( nLookaside==0 || nLookaside==db->lookaside.nOut );
}
void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
  /* Do not delete the table until the reference count reaches zero. */
  if( !pTable ) return;
  if( ((!db || db->pnBytesFreed==0) && (--pTable->nRef)>0) ) return;
  deleteTable(db, pTable);
}


/*
** Unlink the given table from the hash tables and the delete the
** table structure with all its indices and foreign keys.
................................................................................

/*
** Open the sqlite_master table stored in database number iDb for
** writing. The table is opened using cursor 0.
*/
void sqlite3OpenMasterTable(Parse *p, int iDb){
  Vdbe *v = sqlite3GetVdbe(p);
  sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb));
  sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, MASTER_ROOT, iDb, 5);
  if( p->nTab==0 ){
    p->nTab = 1;
  }
}

/*
................................................................................
    pParse->rc = SQLITE_NOMEM_BKPT;
    pParse->nErr++;
    goto begin_table_error;
  }
  pTable->zName = zName;
  pTable->iPKey = -1;
  pTable->pSchema = db->aDb[iDb].pSchema;
  pTable->nRef = 1;
  pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
  assert( pParse->pNewTable==0 );
  pParse->pNewTable = pTable;

  /* If this is the magic sqlite_sequence table used by autoincrement,
  ** then record a pointer to this table in the main database structure
  ** so that INSERT can find the table easily.
................................................................................
    ** SQLITE_MASTER table.  We just need to update that slot with all
    ** the information we've collected.
    */
    sqlite3NestedParse(pParse,
      "UPDATE %Q.%s "
         "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q "
       "WHERE rowid=#%d",
      db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb),
      zType,
      p->zName,
      p->zName,
      pParse->regRoot,
      zStmt,
      pParse->regRowid
    );
................................................................................
  **
  ** The "#NNN" in the SQL is a special constant that means whatever value
  ** is in register NNN.  See grammar rules associated with the TK_REGISTER
  ** token for additional information.
  */
  sqlite3NestedParse(pParse, 
     "UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d",
     pParse->db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), iTable, r1, r1);
#endif
  sqlite3ReleaseTempReg(pParse, r1);
}

/*
** Write VDBE code to erase table pTab and all associated indices on disk.
** Code to update the sqlite_master tables and internal schema definitions
................................................................................
  ** every row that refers to a table of the same name as the one being
  ** dropped. Triggers are handled separately because a trigger can be
  ** created in the temp database that refers to a table in another
  ** database.
  */
  sqlite3NestedParse(pParse, 
      "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
      pDb->zDbSName, SCHEMA_TABLE(iDb), pTab->zName);
  if( !isView && !IsVirtual(pTab) ){
    destroyTable(pParse, pTab);
  }

  /* Remove the table entry from SQLite's internal schema and modify
  ** the schema cookie.
  */
................................................................................
      zStmt = 0;
    }

    /* Add an entry in sqlite_master for this index
    */
    sqlite3NestedParse(pParse, 
        "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
        db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb),
        pIndex->zName,
        pTab->zName,
        iMem,
        zStmt
    );
    sqlite3DbFree(db, zStmt);

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

  /* Generate code to remove the index and from the master table */
  v = sqlite3GetVdbe(pParse);
  if( v ){
    sqlite3BeginWriteOperation(pParse, 1, iDb);
    sqlite3NestedParse(pParse,
       "DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
       db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pIndex->zName
    );
    sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
    sqlite3ChangeCookie(pParse, iDb);
    destroyRootPage(pParse, pIndex->tnum, iDb);
    sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
  }

................................................................................
  assert( nExtra>=1 );
  assert( pSrc!=0 );
  assert( iStart<=pSrc->nSrc );

  /* Allocate additional space if needed */
  if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){
    SrcList *pNew;
    int nAlloc = pSrc->nSrc+nExtra;
    int nGot;
    pNew = sqlite3DbRealloc(db, pSrc,
               sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
    if( pNew==0 ){
      assert( db->mallocFailed );
      return pSrc;
    }
................................................................................
  struct SrcList_item *pItem;
  assert( pDatabase==0 || pTable!=0 );  /* Cannot have C without B */
  assert( db!=0 );
  if( pList==0 ){
    pList = sqlite3DbMallocRawNN(db, sizeof(SrcList) );
    if( pList==0 ) return 0;
    pList->nAlloc = 1;
    pList->nSrc = 0;
  }



  pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc);

  if( db->mallocFailed ){
    sqlite3SrcListDelete(db, pList);
    return 0;
  }
  pItem = &pList->a[pList->nSrc-1];
  if( pDatabase && pDatabase->z==0 ){
    pDatabase = 0;







|
|
|
|







 







|







 







|







 







>
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|
<
>
>
>
|
>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
..
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
..
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
...
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
...
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
...
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
...
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
....
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
....
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
....
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
....
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
....
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
....
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
....
3753
3754
3755
3756
3757
3758
3759
3760

3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772

#ifndef SQLITE_OMIT_SHARED_CACHE
/*
** The TableLock structure is only used by the sqlite3TableLock() and
** codeTableLocks() functions.
*/
struct TableLock {
  int iDb;               /* The database containing the table to be locked */
  int iTab;              /* The root page of the table to be locked */
  u8 isWriteLock;        /* True for write lock.  False for a read lock */
  const char *zLockName; /* Name of the table */
};

/*
** Record the fact that we want to lock a table at run-time.  
**
** The table to be locked has root page iTab and is found in database iDb.
** A read or a write lock can be taken depending on isWritelock.
................................................................................
  pToplevel->aTableLock =
      sqlite3DbReallocOrFree(pToplevel->db, pToplevel->aTableLock, nBytes);
  if( pToplevel->aTableLock ){
    p = &pToplevel->aTableLock[pToplevel->nTableLock++];
    p->iDb = iDb;
    p->iTab = iTab;
    p->isWriteLock = isWriteLock;
    p->zLockName = zName;
  }else{
    pToplevel->nTableLock = 0;
    sqlite3OomFault(pToplevel->db);
  }
}

/*
................................................................................
  pVdbe = sqlite3GetVdbe(pParse);
  assert( pVdbe!=0 ); /* sqlite3GetVdbe cannot fail: VDBE already allocated */

  for(i=0; i<pParse->nTableLock; i++){
    TableLock *p = &pParse->aTableLock[i];
    int p1 = p->iDb;
    sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock,
                      p->zLockName, P4_STATIC);
  }
}
#else
  #define codeTableLocks(x)
#endif

/*
................................................................................
#if SQLITE_USER_AUTHENTICATION
  /* Only the admin user is allowed to know that the sqlite_user table
  ** exists */
  if( db->auth.authLevel<UAUTH_Admin && sqlite3UserAuthTable(zName)!=0 ){
    return 0;
  }
#endif
  while(1){
    for(i=OMIT_TEMPDB; i<db->nDb; i++){
      int j = (i<2) ? i^1 : i;   /* Search TEMP before MAIN */
      if( zDatabase==0 || sqlite3StrICmp(zDatabase, db->aDb[j].zDbSName)==0 ){
        assert( sqlite3SchemaMutexHeld(db, j, 0) );
        p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
        if( p ) return p;
      }
    }
    /* Not found.  If the name we were looking for was temp.sqlite_master
    ** then change the name to sqlite_temp_master and try again. */
    if( sqlite3StrICmp(zName, MASTER_NAME)!=0 ) break;
    if( zDatabase==0 ) break;
    if( sqlite3StrICmp(zDatabase, db->aDb[1].zDbSName)!=0 ) break;
    zName = TEMP_MASTER_NAME;
  }
  return 0;
}

/*
** Locate the in-memory structure that describes a particular database
** table given the name of that table and (optionally) the name of the
** database containing the table.  Return NULL if not found.  Also leave an
** error message in pParse->zErrMsg.
................................................................................

  /* Verify that no lookaside memory was used by schema tables */
  assert( nLookaside==0 || nLookaside==db->lookaside.nOut );
}
void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
  /* Do not delete the table until the reference count reaches zero. */
  if( !pTable ) return;
  if( ((!db || db->pnBytesFreed==0) && (--pTable->nTabRef)>0) ) return;
  deleteTable(db, pTable);
}


/*
** Unlink the given table from the hash tables and the delete the
** table structure with all its indices and foreign keys.
................................................................................

/*
** Open the sqlite_master table stored in database number iDb for
** writing. The table is opened using cursor 0.
*/
void sqlite3OpenMasterTable(Parse *p, int iDb){
  Vdbe *v = sqlite3GetVdbe(p);
  sqlite3TableLock(p, iDb, MASTER_ROOT, 1, MASTER_NAME);
  sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, MASTER_ROOT, iDb, 5);
  if( p->nTab==0 ){
    p->nTab = 1;
  }
}

/*
................................................................................
    pParse->rc = SQLITE_NOMEM_BKPT;
    pParse->nErr++;
    goto begin_table_error;
  }
  pTable->zName = zName;
  pTable->iPKey = -1;
  pTable->pSchema = db->aDb[iDb].pSchema;
  pTable->nTabRef = 1;
  pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
  assert( pParse->pNewTable==0 );
  pParse->pNewTable = pTable;

  /* If this is the magic sqlite_sequence table used by autoincrement,
  ** then record a pointer to this table in the main database structure
  ** so that INSERT can find the table easily.
................................................................................
    ** SQLITE_MASTER table.  We just need to update that slot with all
    ** the information we've collected.
    */
    sqlite3NestedParse(pParse,
      "UPDATE %Q.%s "
         "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q "
       "WHERE rowid=#%d",
      db->aDb[iDb].zDbSName, MASTER_NAME,
      zType,
      p->zName,
      p->zName,
      pParse->regRoot,
      zStmt,
      pParse->regRowid
    );
................................................................................
  **
  ** The "#NNN" in the SQL is a special constant that means whatever value
  ** is in register NNN.  See grammar rules associated with the TK_REGISTER
  ** token for additional information.
  */
  sqlite3NestedParse(pParse, 
     "UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d",
     pParse->db->aDb[iDb].zDbSName, MASTER_NAME, iTable, r1, r1);
#endif
  sqlite3ReleaseTempReg(pParse, r1);
}

/*
** Write VDBE code to erase table pTab and all associated indices on disk.
** Code to update the sqlite_master tables and internal schema definitions
................................................................................
  ** every row that refers to a table of the same name as the one being
  ** dropped. Triggers are handled separately because a trigger can be
  ** created in the temp database that refers to a table in another
  ** database.
  */
  sqlite3NestedParse(pParse, 
      "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
      pDb->zDbSName, MASTER_NAME, pTab->zName);
  if( !isView && !IsVirtual(pTab) ){
    destroyTable(pParse, pTab);
  }

  /* Remove the table entry from SQLite's internal schema and modify
  ** the schema cookie.
  */
................................................................................
      zStmt = 0;
    }

    /* Add an entry in sqlite_master for this index
    */
    sqlite3NestedParse(pParse, 
        "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
        db->aDb[iDb].zDbSName, MASTER_NAME,
        pIndex->zName,
        pTab->zName,
        iMem,
        zStmt
    );
    sqlite3DbFree(db, zStmt);

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

  /* Generate code to remove the index and from the master table */
  v = sqlite3GetVdbe(pParse);
  if( v ){
    sqlite3BeginWriteOperation(pParse, 1, iDb);
    sqlite3NestedParse(pParse,
       "DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
       db->aDb[iDb].zDbSName, MASTER_NAME, pIndex->zName
    );
    sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
    sqlite3ChangeCookie(pParse, iDb);
    destroyRootPage(pParse, pIndex->tnum, iDb);
    sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
  }

................................................................................
  assert( nExtra>=1 );
  assert( pSrc!=0 );
  assert( iStart<=pSrc->nSrc );

  /* Allocate additional space if needed */
  if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){
    SrcList *pNew;
    int nAlloc = pSrc->nSrc*2+nExtra;
    int nGot;
    pNew = sqlite3DbRealloc(db, pSrc,
               sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
    if( pNew==0 ){
      assert( db->mallocFailed );
      return pSrc;
    }
................................................................................
  struct SrcList_item *pItem;
  assert( pDatabase==0 || pTable!=0 );  /* Cannot have C without B */
  assert( db!=0 );
  if( pList==0 ){
    pList = sqlite3DbMallocRawNN(db, sizeof(SrcList) );
    if( pList==0 ) return 0;
    pList->nAlloc = 1;
    pList->nSrc = 1;

    memset(&pList->a[0], 0, sizeof(pList->a[0]));
    pList->a[0].iCursor = -1;
  }else{
    pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc);
  }
  if( db->mallocFailed ){
    sqlite3SrcListDelete(db, pList);
    return 0;
  }
  pItem = &pList->a[pList->nSrc-1];
  if( pDatabase && pDatabase->z==0 ){
    pDatabase = 0;

Changes to src/delete.c.

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  struct SrcList_item *pItem = pSrc->a;
  Table *pTab;
  assert( pItem && pSrc->nSrc==1 );
  pTab = sqlite3LocateTableItem(pParse, 0, pItem);
  sqlite3DeleteTable(pParse->db, pItem->pTab);
  pItem->pTab = pTab;
  if( pTab ){
    pTab->nRef++;
  }
  if( sqlite3IndexedByLookup(pParse, pItem) ){
    pTab = 0;
  }
  return pTab;
}








|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  struct SrcList_item *pItem = pSrc->a;
  Table *pTab;
  assert( pItem && pSrc->nSrc==1 );
  pTab = sqlite3LocateTableItem(pParse, 0, pItem);
  sqlite3DeleteTable(pParse->db, pItem->pTab);
  pItem->pTab = pTab;
  if( pTab ){
    pTab->nTabRef++;
  }
  if( sqlite3IndexedByLookup(pParse, pItem) ){
    pTab = 0;
  }
  return pTab;
}

Changes to src/expr.c.

1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
    pNewItem->pIBIndex = pOldItem->pIBIndex;
    if( pNewItem->fg.isTabFunc ){
      pNewItem->u1.pFuncArg = 
          sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags);
    }
    pTab = pNewItem->pTab = pOldItem->pTab;
    if( pTab ){
      pTab->nRef++;
    }
    pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags);
    pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn, flags);
    pNewItem->pUsing = sqlite3IdListDup(db, pOldItem->pUsing);
    pNewItem->colUsed = pOldItem->colUsed;
  }
  return pNew;







|







1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
    pNewItem->pIBIndex = pOldItem->pIBIndex;
    if( pNewItem->fg.isTabFunc ){
      pNewItem->u1.pFuncArg = 
          sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags);
    }
    pTab = pNewItem->pTab = pOldItem->pTab;
    if( pTab ){
      pTab->nTabRef++;
    }
    pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags);
    pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn, flags);
    pNewItem->pUsing = sqlite3IdListDup(db, pOldItem->pUsing);
    pNewItem->colUsed = pOldItem->colUsed;
  }
  return pNew;

Changes to src/fkey.c.

221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
....
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
    assert( nCol>1 );
    aiCol = (int *)sqlite3DbMallocRawNN(pParse->db, nCol*sizeof(int));
    if( !aiCol ) return 1;
    *paiCol = aiCol;
  }

  for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){
    if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) ){ 
      /* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number
      ** of columns. If each indexed column corresponds to a foreign key
      ** column of pFKey, then this index is a winner.  */

      if( zKey==0 ){
        /* If zKey is NULL, then this foreign key is implicitly mapped to 
        ** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be 
................................................................................
    /* Create a SrcList structure containing the child table.  We need the
    ** child table as a SrcList for sqlite3WhereBegin() */
    pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
    if( pSrc ){
      struct SrcList_item *pItem = pSrc->a;
      pItem->pTab = pFKey->pFrom;
      pItem->zName = pFKey->pFrom->zName;
      pItem->pTab->nRef++;
      pItem->iCursor = pParse->nTab++;
  
      if( regNew!=0 ){
        fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1);
      }
      if( regOld!=0 ){
        int eAction = pFKey->aAction[aChange!=0];







|







 







|







221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
....
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
    assert( nCol>1 );
    aiCol = (int *)sqlite3DbMallocRawNN(pParse->db, nCol*sizeof(int));
    if( !aiCol ) return 1;
    *paiCol = aiCol;
  }

  for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){
    if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) && pIdx->pPartIdxWhere==0 ){ 
      /* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number
      ** of columns. If each indexed column corresponds to a foreign key
      ** column of pFKey, then this index is a winner.  */

      if( zKey==0 ){
        /* If zKey is NULL, then this foreign key is implicitly mapped to 
        ** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be 
................................................................................
    /* Create a SrcList structure containing the child table.  We need the
    ** child table as a SrcList for sqlite3WhereBegin() */
    pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
    if( pSrc ){
      struct SrcList_item *pItem = pSrc->a;
      pItem->pTab = pFKey->pFrom;
      pItem->zName = pFKey->pFrom->zName;
      pItem->pTab->nTabRef++;
      pItem->iCursor = pParse->nTab++;
  
      if( regNew!=0 ){
        fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1);
      }
      if( regOld!=0 ){
        int eAction = pFKey->aAction[aChange!=0];

Changes to src/pager.c.

689
690
691
692
693
694
695

696
697
698
699
700
701
702
....
1014
1015
1016
1017
1018
1019
1020



























1021
1022
1023
1024
1025
1026
1027
....
1829
1830
1831
1832
1833
1834
1835

1836
1837
1838
1839
1840
1841
1842
....
1866
1867
1868
1869
1870
1871
1872

1873
1874
1875
1876
1877
1878
1879
....
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
....
3433
3434
3435
3436
3437
3438
3439

3440
3441
3442
3443
3444
3445
3446
....
4850
4851
4852
4853
4854
4855
4856

4857
4858
4859
4860
4861
4862
4863
....
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273







5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
....
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394

5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418

5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437


5438
5439
5440
5441
5442
5443
5444
....
5457
5458
5459
5460
5461
5462
5463

5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485


5486









































5487
5488























































5489
5490
5491
5492
5493
5494
5495
....
6456
6457
6458
6459
6460
6461
6462

6463
6464
6465
6466
6467
6468
6469
....
6717
6718
6719
6720
6721
6722
6723

6724
6725
6726
6727
6728
6729
6730
....
6789
6790
6791
6792
6793
6794
6795

6796
6797
6798
6799
6800
6801
6802
  int (*xBusyHandler)(void*); /* Function to call when busy */
  void *pBusyHandlerArg;      /* Context argument for xBusyHandler */
  int aStat[3];               /* Total cache hits, misses and writes */
#ifdef SQLITE_TEST
  int nRead;                  /* Database pages read */
#endif
  void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */

#ifdef SQLITE_HAS_CODEC
  void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
  void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */
  void (*xCodecFree)(void*);             /* Destructor for the codec */
  void *pCodec;               /* First argument to xCodec... methods */
#endif
  char *pTmpSpace;            /* Pager.pageSize bytes of space for tmp use */
................................................................................
      , p->journalOff, p->journalHdr
      , (int)p->dbSize, (int)p->dbOrigSize, (int)p->dbFileSize
  );

  return zRet;
}
#endif




























/*
** Return true if it is necessary to write page *pPg into the sub-journal.
** A page needs to be written into the sub-journal if there exists one
** or more open savepoints for which:
**
**   * The page-number is less than or equal to PagerSavepoint.nOrig, and
................................................................................
      pPager->changeCountDone = 0;
      pPager->eState = PAGER_OPEN;
    }else{
      pPager->eState = (isOpen(pPager->jfd) ? PAGER_OPEN : PAGER_READER);
    }
    if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
    pPager->errCode = SQLITE_OK;

  }

  pPager->journalOff = 0;
  pPager->journalHdr = 0;
  pPager->setMaster = 0;
}

................................................................................
       pPager->errCode==SQLITE_FULL ||
       pPager->errCode==SQLITE_OK ||
       (pPager->errCode & 0xff)==SQLITE_IOERR
  );
  if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){
    pPager->errCode = rc;
    pPager->eState = PAGER_ERROR;

  }
  return rc;
}

static int pager_truncate(Pager *pPager, Pgno nPage);

/*
................................................................................
  }
#endif

  sqlite3BitvecDestroy(pPager->pInJournal);
  pPager->pInJournal = 0;
  pPager->nRec = 0;
  if( rc==SQLITE_OK ){
    if( pagerFlushOnCommit(pPager, bCommit) ){
      sqlite3PcacheCleanAll(pPager->pPCache);
    }else{
      sqlite3PcacheClearWritable(pPager->pPCache);
    }
    sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
  }

................................................................................
static void pagerFixMaplimit(Pager *pPager){
#if SQLITE_MAX_MMAP_SIZE>0
  sqlite3_file *fd = pPager->fd;
  if( isOpen(fd) && fd->pMethods->iVersion>=3 ){
    sqlite3_int64 sz;
    sz = pPager->szMmap;
    pPager->bUseFetch = (sz>0);

    sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz);
  }
#endif
}

/*
** Change the maximum size of any memory mapping made of the database file.
................................................................................
    pPager->journalMode = PAGER_JOURNALMODE_OFF;
  }else if( memDb ){
    pPager->journalMode = PAGER_JOURNALMODE_MEMORY;
  }
  /* pPager->xBusyHandler = 0; */
  /* pPager->pBusyHandlerArg = 0; */
  pPager->xReiniter = xReinit;

  /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
  /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */

  *ppPager = pPager;
  return SQLITE_OK;
}

................................................................................
static void pagerUnlockIfUnused(Pager *pPager){
  if( pPager->nMmapOut==0 && (sqlite3PcacheRefCount(pPager->pPCache)==0) ){
    pagerUnlockAndRollback(pPager);
  }
}

/*
** Acquire a reference to page number pgno in pager pPager (a page
** reference has type DbPage*). If the requested reference is 
** successfully obtained, it is copied to *ppPage and SQLITE_OK returned.
**







** If the requested page is already in the cache, it is returned. 
** Otherwise, a new page object is allocated and populated with data
** read from the database file. In some cases, the pcache module may
** choose not to allocate a new page object and may reuse an existing
** object with no outstanding references.
**
** The extra data appended to a page is always initialized to zeros the 
** first time a page is loaded into memory. If the page requested is 
** already in the cache when this function is called, then the extra
** data is left as it was when the page object was last used.
**
** If the database image is smaller than the requested page or if a 
** non-zero value is passed as the noContent parameter and the 
** requested page is not already stored in the cache, then no 
** actual disk read occurs. In this case the memory image of the 
** page is initialized to all zeros. 
**
** If noContent is true, it means that we do not care about the contents
** of the page. This occurs in two scenarios:
**
**   a) When reading a free-list leaf page from the database, and
**
**   b) When a savepoint is being rolled back and we need to load
**      a new page into the cache to be filled with the data read
**      from the savepoint journal.
**
** If noContent is true, then the data returned is zeroed instead of
** being read from the database. Additionally, the bits corresponding
** to pgno in Pager.pInJournal (bitvec of pages already written to the
** journal file) and the PagerSavepoint.pInSavepoint bitvecs of any open
** savepoints are set. This means if the page is made writable at any
** point in the future, using a call to sqlite3PagerWrite(), its contents
** will not be journaled. This saves IO.
**
** The acquisition might fail for several reasons.  In all cases,
................................................................................
** to find a page in the in-memory cache first.  If the page is not already
** in memory, this routine goes to disk to read it in whereas Lookup()
** just returns 0.  This routine acquires a read-lock the first time it
** has to go to disk, and could also playback an old journal if necessary.
** Since Lookup() never goes to disk, it never has to deal with locks
** or journal files.
*/
int sqlite3PagerGet(
  Pager *pPager,      /* The pager open on the database file */
  Pgno pgno,          /* Page number to fetch */
  DbPage **ppPage,    /* Write a pointer to the page here */
  int flags           /* PAGER_GET_XXX flags */
){
  int rc = SQLITE_OK;
  PgHdr *pPg = 0;
  u32 iFrame = 0;                 /* Frame to read from WAL file */
  const int noContent = (flags & PAGER_GET_NOCONTENT);

  /* It is acceptable to use a read-only (mmap) page for any page except
  ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
  ** flag was specified by the caller. And so long as the db is not a 
  ** temporary or in-memory database.  */
  const int bMmapOk = (pgno>1 && USEFETCH(pPager)
   && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY))
#ifdef SQLITE_HAS_CODEC
   && pPager->xCodec==0
#endif
  );

  /* Optimization note:  Adding the "pgno<=1" term before "pgno==0" here
  ** allows the compiler optimizer to reuse the results of the "pgno>1"
  ** test in the previous statement, and avoid testing pgno==0 in the
  ** common case where pgno is large. */
  if( pgno<=1 && pgno==0 ){
    return SQLITE_CORRUPT_BKPT;
  }
  assert( pPager->eState>=PAGER_READER );
  assert( assert_pager_state(pPager) );
  assert( noContent==0 || bMmapOk==0 );

  assert( pPager->hasHeldSharedLock==1 );

  /* If the pager is in the error state, return an error immediately. 
  ** Otherwise, request the page from the PCache layer. */
  if( pPager->errCode!=SQLITE_OK ){
    rc = pPager->errCode;
  }else{
    if( bMmapOk && pagerUseWal(pPager) ){
      rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
      if( rc!=SQLITE_OK ) goto pager_acquire_err;
    }

    if( bMmapOk && iFrame==0 ){
      void *pData = 0;

      rc = sqlite3OsFetch(pPager->fd, 
          (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData
      );

      if( rc==SQLITE_OK && pData ){
        if( pPager->eState>PAGER_READER || pPager->tempFile ){
          pPg = sqlite3PagerLookup(pPager, pgno);
        }
        if( pPg==0 ){
          rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg);
        }else{
          sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData);
        }
        if( pPg ){
          assert( rc==SQLITE_OK );
          *ppPage = pPg;
          return SQLITE_OK;
        }
      }
      if( rc!=SQLITE_OK ){
        goto pager_acquire_err;
      }
    }

    {
      sqlite3_pcache_page *pBase;
      pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3);
      if( pBase==0 ){

        rc = sqlite3PcacheFetchStress(pPager->pPCache, pgno, &pBase);
        if( rc!=SQLITE_OK ) goto pager_acquire_err;
        if( pBase==0 ){
          pPg = *ppPage = 0;
          rc = SQLITE_NOMEM_BKPT;
          goto pager_acquire_err;
        }
      }
      pPg = *ppPage = sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pBase);
      assert( pPg!=0 );
    }
  }

  if( rc!=SQLITE_OK ){
    /* Either the call to sqlite3PcacheFetch() returned an error or the
    ** pager was already in the error-state when this function was called.
    ** Set pPg to 0 and jump to the exception handler.  */
    pPg = 0;
    goto pager_acquire_err;
  }
  assert( pPg==(*ppPage) );
  assert( pPg->pgno==pgno );
  assert( pPg->pPager==pPager || pPg->pPager==0 );


  if( pPg->pPager && !noContent ){
    /* In this case the pcache already contains an initialized copy of
    ** the page. Return without further ado.  */
    assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) );
    pPager->aStat[PAGER_STAT_HIT]++;
    return SQLITE_OK;

  }else{
    /* The pager cache has created a new page. Its content needs to 
    ** be initialized.  */

    pPg->pPager = pPager;

    /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
    ** number greater than this, or the unused locking-page, is requested. */
    if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){
      rc = SQLITE_CORRUPT_BKPT;
      goto pager_acquire_err;
    }



    assert( !isOpen(pPager->fd) || !MEMDB );
    if( !isOpen(pPager->fd) || pPager->dbSize<pgno || noContent ){
      if( pgno>pPager->mxPgno ){
        rc = SQLITE_FULL;
        goto pager_acquire_err;
      }
................................................................................
        TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno);
        testcase( rc==SQLITE_NOMEM );
        sqlite3EndBenignMalloc();
      }
      memset(pPg->pData, 0, pPager->pageSize);
      IOTRACE(("ZERO %p %d\n", pPager, pgno));
    }else{

      if( pagerUseWal(pPager) && bMmapOk==0 ){
        rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
        if( rc!=SQLITE_OK ) goto pager_acquire_err;
      }
      assert( pPg->pPager==pPager );
      pPager->aStat[PAGER_STAT_MISS]++;
      rc = readDbPage(pPg, iFrame);
      if( rc!=SQLITE_OK ){
        goto pager_acquire_err;
      }
    }
    pager_set_pagehash(pPg);
  }

  return SQLITE_OK;

pager_acquire_err:
  assert( rc!=SQLITE_OK );
  if( pPg ){
    sqlite3PcacheDrop(pPg);
  }
  pagerUnlockIfUnused(pPager);












































  *ppPage = 0;
  return rc;























































}

/*
** Acquire a page if it is already in the in-memory cache.  Do
** not read the page from disk.  Return a pointer to the page,
** or 0 if the page is not in cache. 
**
................................................................................
    if( !MEMDB && eState>PAGER_WRITER_LOCKED ){
      /* This can happen using journal_mode=off. Move the pager to the error 
      ** state to indicate that the contents of the cache may not be trusted.
      ** Any active readers will get SQLITE_ABORT.
      */
      pPager->errCode = SQLITE_ABORT;
      pPager->eState = PAGER_ERROR;

      return rc;
    }
  }else{
    rc = pager_playback(pPager, 0);
  }

  assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK );
................................................................................
    ** can be rolled back at the ZipVFS level.  */
    else if( 
        pPager->journalMode==PAGER_JOURNALMODE_OFF 
     && pPager->eState>=PAGER_WRITER_CACHEMOD
    ){
      pPager->errCode = SQLITE_ABORT;
      pPager->eState = PAGER_ERROR;

    }
#endif
  }

  return rc;
}

................................................................................
  void *pCodec
){
  if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
  pPager->xCodec = pPager->memDb ? 0 : xCodec;
  pPager->xCodecSizeChng = xCodecSizeChng;
  pPager->xCodecFree = xCodecFree;
  pPager->pCodec = pCodec;

  pagerReportSize(pPager);
}
void *sqlite3PagerGetCodec(Pager *pPager){
  return pPager->pCodec;
}

/*







>







 







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







 







>







 







>







 







|







 







>







 







>







 







|
|


>
>
>
>
>
>
>











|
|




|
|







|
|







 







|






|
|
|

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


<
<


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
>
|
|
|
<
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<




>









|
|
|
|
|
|
|



>
>







 







>
|












<








>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







 







>







 







>







689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
....
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
1053
1054
1055
....
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
....
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
....
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
....
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
....
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
....
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
....
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369

















5370
5371


5372
5373







































5374
5375
5376
5377
5378
5379

5380
5381
5382
5383
5384











5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
....
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450

5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
....
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
....
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
....
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
  int (*xBusyHandler)(void*); /* Function to call when busy */
  void *pBusyHandlerArg;      /* Context argument for xBusyHandler */
  int aStat[3];               /* Total cache hits, misses and writes */
#ifdef SQLITE_TEST
  int nRead;                  /* Database pages read */
#endif
  void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
  int (*xGet)(Pager*,Pgno,DbPage**,int); /* Routine to fetch a patch */
#ifdef SQLITE_HAS_CODEC
  void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
  void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */
  void (*xCodecFree)(void*);             /* Destructor for the codec */
  void *pCodec;               /* First argument to xCodec... methods */
#endif
  char *pTmpSpace;            /* Pager.pageSize bytes of space for tmp use */
................................................................................
      , p->journalOff, p->journalHdr
      , (int)p->dbSize, (int)p->dbOrigSize, (int)p->dbFileSize
  );

  return zRet;
}
#endif

/* Forward references to the various page getters */
static int getPageNormal(Pager*,Pgno,DbPage**,int);
static int getPageError(Pager*,Pgno,DbPage**,int);
#if SQLITE_MAX_MMAP_SIZE>0
static int getPageMMap(Pager*,Pgno,DbPage**,int);
#endif

/*
** Set the Pager.xGet method for the appropriate routine used to fetch
** content from the pager.
*/
static void setGetterMethod(Pager *pPager){
  if( pPager->errCode ){
    pPager->xGet = getPageError;
#if SQLITE_MAX_MMAP_SIZE>0
  }else if( USEFETCH(pPager)
#ifdef SQLITE_HAS_CODEC
   && pPager->xCodec==0
#endif
  ){
    pPager->xGet = getPageMMap;
#endif /* SQLITE_MAX_MMAP_SIZE>0 */
  }else{
    pPager->xGet = getPageNormal;
  }
}

/*
** Return true if it is necessary to write page *pPg into the sub-journal.
** A page needs to be written into the sub-journal if there exists one
** or more open savepoints for which:
**
**   * The page-number is less than or equal to PagerSavepoint.nOrig, and
................................................................................
      pPager->changeCountDone = 0;
      pPager->eState = PAGER_OPEN;
    }else{
      pPager->eState = (isOpen(pPager->jfd) ? PAGER_OPEN : PAGER_READER);
    }
    if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
    pPager->errCode = SQLITE_OK;
    setGetterMethod(pPager);
  }

  pPager->journalOff = 0;
  pPager->journalHdr = 0;
  pPager->setMaster = 0;
}

................................................................................
       pPager->errCode==SQLITE_FULL ||
       pPager->errCode==SQLITE_OK ||
       (pPager->errCode & 0xff)==SQLITE_IOERR
  );
  if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){
    pPager->errCode = rc;
    pPager->eState = PAGER_ERROR;
    setGetterMethod(pPager);
  }
  return rc;
}

static int pager_truncate(Pager *pPager, Pgno nPage);

/*
................................................................................
  }
#endif

  sqlite3BitvecDestroy(pPager->pInJournal);
  pPager->pInJournal = 0;
  pPager->nRec = 0;
  if( rc==SQLITE_OK ){
    if( MEMDB || pagerFlushOnCommit(pPager, bCommit) ){
      sqlite3PcacheCleanAll(pPager->pPCache);
    }else{
      sqlite3PcacheClearWritable(pPager->pPCache);
    }
    sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
  }

................................................................................
static void pagerFixMaplimit(Pager *pPager){
#if SQLITE_MAX_MMAP_SIZE>0
  sqlite3_file *fd = pPager->fd;
  if( isOpen(fd) && fd->pMethods->iVersion>=3 ){
    sqlite3_int64 sz;
    sz = pPager->szMmap;
    pPager->bUseFetch = (sz>0);
    setGetterMethod(pPager);
    sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz);
  }
#endif
}

/*
** Change the maximum size of any memory mapping made of the database file.
................................................................................
    pPager->journalMode = PAGER_JOURNALMODE_OFF;
  }else if( memDb ){
    pPager->journalMode = PAGER_JOURNALMODE_MEMORY;
  }
  /* pPager->xBusyHandler = 0; */
  /* pPager->pBusyHandlerArg = 0; */
  pPager->xReiniter = xReinit;
  setGetterMethod(pPager);
  /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
  /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */

  *ppPager = pPager;
  return SQLITE_OK;
}

................................................................................
static void pagerUnlockIfUnused(Pager *pPager){
  if( pPager->nMmapOut==0 && (sqlite3PcacheRefCount(pPager->pPCache)==0) ){
    pagerUnlockAndRollback(pPager);
  }
}

/*
** The page getter methods each try to acquire a reference to a
** page with page number pgno. If the requested reference is 
** successfully obtained, it is copied to *ppPage and SQLITE_OK returned.
**
** There are different implementations of the getter method depending
** on the current state of the pager.
**
**     getPageNormal()         --  The normal getter
**     getPageError()          --  Used if the pager is in an error state
**     getPageMmap()           --  Used if memory-mapped I/O is enabled
**
** If the requested page is already in the cache, it is returned. 
** Otherwise, a new page object is allocated and populated with data
** read from the database file. In some cases, the pcache module may
** choose not to allocate a new page object and may reuse an existing
** object with no outstanding references.
**
** The extra data appended to a page is always initialized to zeros the 
** first time a page is loaded into memory. If the page requested is 
** already in the cache when this function is called, then the extra
** data is left as it was when the page object was last used.
**
** If the database image is smaller than the requested page or if 
** the flags parameter contains the PAGER_GET_NOCONTENT bit and the 
** requested page is not already stored in the cache, then no 
** actual disk read occurs. In this case the memory image of the 
** page is initialized to all zeros. 
**
** If PAGER_GET_NOCONTENT is true, it means that we do not care about
** the contents of the page. This occurs in two scenarios:
**
**   a) When reading a free-list leaf page from the database, and
**
**   b) When a savepoint is being rolled back and we need to load
**      a new page into the cache to be filled with the data read
**      from the savepoint journal.
**
** If PAGER_GET_NOCONTENT is true, then the data returned is zeroed instead
** of being read from the database. Additionally, the bits corresponding
** to pgno in Pager.pInJournal (bitvec of pages already written to the
** journal file) and the PagerSavepoint.pInSavepoint bitvecs of any open
** savepoints are set. This means if the page is made writable at any
** point in the future, using a call to sqlite3PagerWrite(), its contents
** will not be journaled. This saves IO.
**
** The acquisition might fail for several reasons.  In all cases,
................................................................................
** to find a page in the in-memory cache first.  If the page is not already
** in memory, this routine goes to disk to read it in whereas Lookup()
** just returns 0.  This routine acquires a read-lock the first time it
** has to go to disk, and could also playback an old journal if necessary.
** Since Lookup() never goes to disk, it never has to deal with locks
** or journal files.
*/
static int getPageNormal(
  Pager *pPager,      /* The pager open on the database file */
  Pgno pgno,          /* Page number to fetch */
  DbPage **ppPage,    /* Write a pointer to the page here */
  int flags           /* PAGER_GET_XXX flags */
){
  int rc = SQLITE_OK;
  PgHdr *pPg;
  u8 noContent;                   /* True if PAGER_GET_NOCONTENT is set */
  sqlite3_pcache_page *pBase;

  assert( pPager->errCode==SQLITE_OK );

















  assert( pPager->eState>=PAGER_READER );
  assert( assert_pager_state(pPager) );


  assert( pPager->hasHeldSharedLock==1 );








































  pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3);
  if( pBase==0 ){
    pPg = 0;
    rc = sqlite3PcacheFetchStress(pPager->pPCache, pgno, &pBase);
    if( rc!=SQLITE_OK ) goto pager_acquire_err;
    if( pBase==0 ){

      rc = SQLITE_NOMEM_BKPT;
      goto pager_acquire_err;
    }
  }
  pPg = *ppPage = sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pBase);











  assert( pPg==(*ppPage) );
  assert( pPg->pgno==pgno );
  assert( pPg->pPager==pPager || pPg->pPager==0 );

  noContent = (flags & PAGER_GET_NOCONTENT)!=0;
  if( pPg->pPager && !noContent ){
    /* In this case the pcache already contains an initialized copy of
    ** the page. Return without further ado.  */
    assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) );
    pPager->aStat[PAGER_STAT_HIT]++;
    return SQLITE_OK;

  }else{
    /* The pager cache has created a new page. Its content needs to 
    ** be initialized. But first some error checks:
    **
    ** (1) Minimum page number is 1
    ** (2) The maximum page number is 2^31
    ** (3) Never try to fetch the locking page
    */
    if( pgno==0 || pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){
      rc = SQLITE_CORRUPT_BKPT;
      goto pager_acquire_err;
    }

    pPg->pPager = pPager;

    assert( !isOpen(pPager->fd) || !MEMDB );
    if( !isOpen(pPager->fd) || pPager->dbSize<pgno || noContent ){
      if( pgno>pPager->mxPgno ){
        rc = SQLITE_FULL;
        goto pager_acquire_err;
      }
................................................................................
        TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno);
        testcase( rc==SQLITE_NOMEM );
        sqlite3EndBenignMalloc();
      }
      memset(pPg->pData, 0, pPager->pageSize);
      IOTRACE(("ZERO %p %d\n", pPager, pgno));
    }else{
      u32 iFrame = 0;                 /* Frame to read from WAL file */
      if( pagerUseWal(pPager) ){
        rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
        if( rc!=SQLITE_OK ) goto pager_acquire_err;
      }
      assert( pPg->pPager==pPager );
      pPager->aStat[PAGER_STAT_MISS]++;
      rc = readDbPage(pPg, iFrame);
      if( rc!=SQLITE_OK ){
        goto pager_acquire_err;
      }
    }
    pager_set_pagehash(pPg);
  }

  return SQLITE_OK;

pager_acquire_err:
  assert( rc!=SQLITE_OK );
  if( pPg ){
    sqlite3PcacheDrop(pPg);
  }
  pagerUnlockIfUnused(pPager);
  *ppPage = 0;
  return rc;
}

#if SQLITE_MAX_MMAP_SIZE>0
/* The page getter for when memory-mapped I/O is enabled */
static int getPageMMap(
  Pager *pPager,      /* The pager open on the database file */
  Pgno pgno,          /* Page number to fetch */
  DbPage **ppPage,    /* Write a pointer to the page here */
  int flags           /* PAGER_GET_XXX flags */
){
  int rc = SQLITE_OK;
  PgHdr *pPg = 0;
  u32 iFrame = 0;                 /* Frame to read from WAL file */

  /* It is acceptable to use a read-only (mmap) page for any page except
  ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
  ** flag was specified by the caller. And so long as the db is not a 
  ** temporary or in-memory database.  */
  const int bMmapOk = (pgno>1
   && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY))
  );

  assert( USEFETCH(pPager) );
#ifdef SQLITE_HAS_CODEC
  assert( pPager->xCodec==0 );
#endif

  /* Optimization note:  Adding the "pgno<=1" term before "pgno==0" here
  ** allows the compiler optimizer to reuse the results of the "pgno>1"
  ** test in the previous statement, and avoid testing pgno==0 in the
  ** common case where pgno is large. */
  if( pgno<=1 && pgno==0 ){
    return SQLITE_CORRUPT_BKPT;
  }
  assert( pPager->eState>=PAGER_READER );
  assert( assert_pager_state(pPager) );
  assert( pPager->hasHeldSharedLock==1 );
  assert( pPager->errCode==SQLITE_OK );

  if( bMmapOk && pagerUseWal(pPager) ){
    rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
    if( rc!=SQLITE_OK ){
      *ppPage = 0;
      return rc;
    }
  }
  if( bMmapOk && iFrame==0 ){
    void *pData = 0;
    rc = sqlite3OsFetch(pPager->fd, 
        (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData
    );
    if( rc==SQLITE_OK && pData ){
      if( pPager->eState>PAGER_READER || pPager->tempFile ){
        pPg = sqlite3PagerLookup(pPager, pgno);
      }
      if( pPg==0 ){
        rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg);
     }else{
        sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData);
      }
      if( pPg ){
        assert( rc==SQLITE_OK );
        *ppPage = pPg;
        return SQLITE_OK;
      }
    }
    if( rc!=SQLITE_OK ){
      *ppPage = 0;
      return rc;
    }
  }
  return getPageNormal(pPager, pgno, ppPage, flags);
}
#endif /* SQLITE_MAX_MMAP_SIZE>0 */

/* The page getter method for when the pager is an error state */
static int getPageError(
  Pager *pPager,      /* The pager open on the database file */
  Pgno pgno,          /* Page number to fetch */
  DbPage **ppPage,    /* Write a pointer to the page here */
  int flags           /* PAGER_GET_XXX flags */
){
  UNUSED_PARAMETER(pgno);
  UNUSED_PARAMETER(flags);
  assert( pPager->errCode!=SQLITE_OK );
  *ppPage = 0;
  return pPager->errCode;
}


/* Dispatch all page fetch requests to the appropriate getter method.
*/
int sqlite3PagerGet(
  Pager *pPager,      /* The pager open on the database file */
  Pgno pgno,          /* Page number to fetch */
  DbPage **ppPage,    /* Write a pointer to the page here */
  int flags           /* PAGER_GET_XXX flags */
){
  return pPager->xGet(pPager, pgno, ppPage, flags);
}

/*
** Acquire a page if it is already in the in-memory cache.  Do
** not read the page from disk.  Return a pointer to the page,
** or 0 if the page is not in cache. 
**
................................................................................
    if( !MEMDB && eState>PAGER_WRITER_LOCKED ){
      /* This can happen using journal_mode=off. Move the pager to the error 
      ** state to indicate that the contents of the cache may not be trusted.
      ** Any active readers will get SQLITE_ABORT.
      */
      pPager->errCode = SQLITE_ABORT;
      pPager->eState = PAGER_ERROR;
      setGetterMethod(pPager);
      return rc;
    }
  }else{
    rc = pager_playback(pPager, 0);
  }

  assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK );
................................................................................
    ** can be rolled back at the ZipVFS level.  */
    else if( 
        pPager->journalMode==PAGER_JOURNALMODE_OFF 
     && pPager->eState>=PAGER_WRITER_CACHEMOD
    ){
      pPager->errCode = SQLITE_ABORT;
      pPager->eState = PAGER_ERROR;
      setGetterMethod(pPager);
    }
#endif
  }

  return rc;
}

................................................................................
  void *pCodec
){
  if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
  pPager->xCodec = pPager->memDb ? 0 : xCodec;
  pPager->xCodecSizeChng = xCodecSizeChng;
  pPager->xCodecFree = xCodecFree;
  pPager->pCodec = pCodec;
  setGetterMethod(pPager);
  pagerReportSize(pPager);
}
void *sqlite3PagerGetCodec(Pager *pPager){
  return pPager->pCodec;
}

/*

Changes to src/pcache.c.

104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
...
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
**
**          assert( sqlite3PcachePageSanity(pPg) );
*/
#if SQLITE_DEBUG
int sqlite3PcachePageSanity(PgHdr *pPg){
  PCache *pCache;
  assert( pPg!=0 );
  assert( pPg->pgno>0 );    /* Page number is 1 or more */
  pCache = pPg->pCache;
  assert( pCache!=0 );      /* Every page has an associated PCache */
  if( pPg->flags & PGHDR_CLEAN ){
    assert( (pPg->flags & PGHDR_DIRTY)==0 );/* Cannot be both CLEAN and DIRTY */
    assert( pCache->pDirty!=pPg );          /* CLEAN pages not on dirty list */
    assert( pCache->pDirtyTail!=pPg );
  }
................................................................................
){
  int eCreate;
  sqlite3_pcache_page *pRes;

  assert( pCache!=0 );
  assert( pCache->pCache!=0 );
  assert( createFlag==3 || createFlag==0 );
  assert( pgno>0 );
  assert( pCache->eCreate==((pCache->bPurgeable && pCache->pDirty) ? 1 : 2) );

  /* eCreate defines what to do if the page does not exist.
  **    0     Do not allocate a new page.  (createFlag==0)
  **    1     Allocate a new page if doing so is inexpensive.
  **          (createFlag==1 AND bPurgeable AND pDirty)
  **    2     Allocate a new page even it doing so is difficult.







|







 







<







104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
...
368
369
370
371
372
373
374

375
376
377
378
379
380
381
**
**          assert( sqlite3PcachePageSanity(pPg) );
*/
#if SQLITE_DEBUG
int sqlite3PcachePageSanity(PgHdr *pPg){
  PCache *pCache;
  assert( pPg!=0 );
  assert( pPg->pgno>0 || pPg->pPager==0 );    /* Page number is 1 or more */
  pCache = pPg->pCache;
  assert( pCache!=0 );      /* Every page has an associated PCache */
  if( pPg->flags & PGHDR_CLEAN ){
    assert( (pPg->flags & PGHDR_DIRTY)==0 );/* Cannot be both CLEAN and DIRTY */
    assert( pCache->pDirty!=pPg );          /* CLEAN pages not on dirty list */
    assert( pCache->pDirtyTail!=pPg );
  }
................................................................................
){
  int eCreate;
  sqlite3_pcache_page *pRes;

  assert( pCache!=0 );
  assert( pCache->pCache!=0 );
  assert( createFlag==3 || createFlag==0 );

  assert( pCache->eCreate==((pCache->bPurgeable && pCache->pDirty) ? 1 : 2) );

  /* eCreate defines what to do if the page does not exist.
  **    0     Do not allocate a new page.  (createFlag==0)
  **    1     Allocate a new page if doing so is inexpensive.
  **          (createFlag==1 AND bPurgeable AND pDirty)
  **    2     Allocate a new page even it doing so is difficult.

Changes to src/select.c.

1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
....
2033
2034
2035
2036
2037
2038
2039

2040
2041
2042
2043
2044
2045
2046
....
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
....
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
....
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
....
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
....
5166
5167
5168
5169
5170
5171
5172

5173

5174
5175
5176
5177
5178
5179
5180
  pTab = sqlite3DbMallocZero(db, sizeof(Table) );
  if( pTab==0 ){
    return 0;
  }
  /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
  ** is disabled */
  assert( db->lookaside.bDisable );
  pTab->nRef = 1;
  pTab->zName = 0;
  pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
  sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
  sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect);
  pTab->iPKey = -1;
  if( db->mallocFailed ){
    sqlite3DeleteTable(db, pTab);
................................................................................
  int regLimit, regOffset;      /* Registers used by LIMIT and OFFSET */

  /* Obtain authorization to do a recursive query */
  if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return;

  /* Process the LIMIT and OFFSET clauses, if they exist */
  addrBreak = sqlite3VdbeMakeLabel(v);

  computeLimitRegisters(pParse, p, addrBreak);
  pLimit = p->pLimit;
  pOffset = p->pOffset;
  regLimit = p->iLimit;
  regOffset = p->iOffset;
  p->pLimit = p->pOffset = 0;
  p->iLimit = p->iOffset = 0;
................................................................................
  ** complete, since there may still exist Expr.pTab entries that
  ** refer to the subquery even after flattening.  Ticket #3346.
  **
  ** pSubitem->pTab is always non-NULL by test restrictions and tests above.
  */
  if( ALWAYS(pSubitem->pTab!=0) ){
    Table *pTabToDel = pSubitem->pTab;
    if( pTabToDel->nRef==1 ){
      Parse *pToplevel = sqlite3ParseToplevel(pParse);
      pTabToDel->pNextZombie = pToplevel->pZombieTab;
      pToplevel->pZombieTab = pTabToDel;
    }else{
      pTabToDel->nRef--;
    }
    pSubitem->pTab = 0;
  }

  /* The following loop runs once for each term in a compound-subquery
  ** flattening (as described above).  If we are doing a different kind
  ** of flattening - a flattening other than a compound-subquery flattening -
................................................................................
      return SQLITE_ERROR;
    }
    if( cannotBeFunction(pParse, pFrom) ) return SQLITE_ERROR;

    assert( pFrom->pTab==0 );
    pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
    if( pTab==0 ) return WRC_Abort;
    pTab->nRef = 1;
    pTab->zName = sqlite3DbStrDup(db, pCte->zName);
    pTab->iPKey = -1;
    pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
    pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
    pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
    if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
    assert( pFrom->pSelect );
................................................................................
        struct SrcList_item *pItem = &pSrc->a[i];
        if( pItem->zDatabase==0 
         && pItem->zName!=0 
         && 0==sqlite3StrICmp(pItem->zName, pCte->zName)
          ){
          pItem->pTab = pTab;
          pItem->fg.isRecursive = 1;
          pTab->nRef++;
          pSel->selFlags |= SF_Recursive;
        }
      }
    }

    /* Only one recursive reference is permitted. */ 
    if( pTab->nRef>2 ){
      sqlite3ErrorMsg(
          pParse, "multiple references to recursive table: %s", pCte->zName
      );
      return SQLITE_ERROR;
    }
    assert( pTab->nRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nRef==2 ));

    pCte->zCteErr = "circular reference: %s";
    pSavedWith = pParse->pWith;
    pParse->pWith = pWith;
    sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel);
    pParse->pWith = pWith;

................................................................................
      Select *pSel = pFrom->pSelect;
      /* A sub-query in the FROM clause of a SELECT */
      assert( pSel!=0 );
      assert( pFrom->pTab==0 );
      if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
      pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
      if( pTab==0 ) return WRC_Abort;
      pTab->nRef = 1;
      pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab);
      while( pSel->pPrior ){ pSel = pSel->pPrior; }
      sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
      pTab->iPKey = -1;
      pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
      pTab->tabFlags |= TF_Ephemeral;
#endif
    }else{
      /* An ordinary table or view name in the FROM clause */
      assert( pFrom->pTab==0 );
      pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
      if( pTab==0 ) return WRC_Abort;
      if( pTab->nRef==0xffff ){
        sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535",
           pTab->zName);
        pFrom->pTab = 0;
        return WRC_Abort;
      }
      pTab->nRef++;
      if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){
        return WRC_Abort;
      }
#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
      if( IsVirtual(pTab) || pTab->pSelect ){
        i16 nCol;
        if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
................................................................................
  if( pDest->eDest==SRT_EphemTab ){
    sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr);
  }

  /* Set the limiter.
  */
  iEnd = sqlite3VdbeMakeLabel(v);

  p->nSelectRow = 320;  /* 4 billion rows */

  computeLimitRegisters(pParse, p, iEnd);
  if( p->iLimit==0 && sSort.addrSortIndex>=0 ){
    sqlite3VdbeChangeOpcode(v, sSort.addrSortIndex, OP_SorterOpen);
    sSort.sortFlags |= SORTFLAG_UseSorter;
  }

  /* Open an ephemeral index to use for the distinct set.







|







 







>







 







|




|







 







|







 







|






|





|







 







|












|





|







 







>
|
>







1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
....
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
....
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
....
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
....
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
....
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
....
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
  pTab = sqlite3DbMallocZero(db, sizeof(Table) );
  if( pTab==0 ){
    return 0;
  }
  /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
  ** is disabled */
  assert( db->lookaside.bDisable );
  pTab->nTabRef = 1;
  pTab->zName = 0;
  pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
  sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
  sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect);
  pTab->iPKey = -1;
  if( db->mallocFailed ){
    sqlite3DeleteTable(db, pTab);
................................................................................
  int regLimit, regOffset;      /* Registers used by LIMIT and OFFSET */

  /* Obtain authorization to do a recursive query */
  if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return;

  /* Process the LIMIT and OFFSET clauses, if they exist */
  addrBreak = sqlite3VdbeMakeLabel(v);
  p->nSelectRow = 320;  /* 4 billion rows */
  computeLimitRegisters(pParse, p, addrBreak);
  pLimit = p->pLimit;
  pOffset = p->pOffset;
  regLimit = p->iLimit;
  regOffset = p->iOffset;
  p->pLimit = p->pOffset = 0;
  p->iLimit = p->iOffset = 0;
................................................................................
  ** complete, since there may still exist Expr.pTab entries that
  ** refer to the subquery even after flattening.  Ticket #3346.
  **
  ** pSubitem->pTab is always non-NULL by test restrictions and tests above.
  */
  if( ALWAYS(pSubitem->pTab!=0) ){
    Table *pTabToDel = pSubitem->pTab;
    if( pTabToDel->nTabRef==1 ){
      Parse *pToplevel = sqlite3ParseToplevel(pParse);
      pTabToDel->pNextZombie = pToplevel->pZombieTab;
      pToplevel->pZombieTab = pTabToDel;
    }else{
      pTabToDel->nTabRef--;
    }
    pSubitem->pTab = 0;
  }

  /* The following loop runs once for each term in a compound-subquery
  ** flattening (as described above).  If we are doing a different kind
  ** of flattening - a flattening other than a compound-subquery flattening -
................................................................................
      return SQLITE_ERROR;
    }
    if( cannotBeFunction(pParse, pFrom) ) return SQLITE_ERROR;

    assert( pFrom->pTab==0 );
    pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
    if( pTab==0 ) return WRC_Abort;
    pTab->nTabRef = 1;
    pTab->zName = sqlite3DbStrDup(db, pCte->zName);
    pTab->iPKey = -1;
    pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
    pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
    pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
    if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
    assert( pFrom->pSelect );
................................................................................
        struct SrcList_item *pItem = &pSrc->a[i];
        if( pItem->zDatabase==0 
         && pItem->zName!=0 
         && 0==sqlite3StrICmp(pItem->zName, pCte->zName)
          ){
          pItem->pTab = pTab;
          pItem->fg.isRecursive = 1;
          pTab->nTabRef++;
          pSel->selFlags |= SF_Recursive;
        }
      }
    }

    /* Only one recursive reference is permitted. */ 
    if( pTab->nTabRef>2 ){
      sqlite3ErrorMsg(
          pParse, "multiple references to recursive table: %s", pCte->zName
      );
      return SQLITE_ERROR;
    }
    assert( pTab->nTabRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 ));

    pCte->zCteErr = "circular reference: %s";
    pSavedWith = pParse->pWith;
    pParse->pWith = pWith;
    sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel);
    pParse->pWith = pWith;

................................................................................
      Select *pSel = pFrom->pSelect;
      /* A sub-query in the FROM clause of a SELECT */
      assert( pSel!=0 );
      assert( pFrom->pTab==0 );
      if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
      pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
      if( pTab==0 ) return WRC_Abort;
      pTab->nTabRef = 1;
      pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab);
      while( pSel->pPrior ){ pSel = pSel->pPrior; }
      sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
      pTab->iPKey = -1;
      pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
      pTab->tabFlags |= TF_Ephemeral;
#endif
    }else{
      /* An ordinary table or view name in the FROM clause */
      assert( pFrom->pTab==0 );
      pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
      if( pTab==0 ) return WRC_Abort;
      if( pTab->nTabRef>=0xffff ){
        sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535",
           pTab->zName);
        pFrom->pTab = 0;
        return WRC_Abort;
      }
      pTab->nTabRef++;
      if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){
        return WRC_Abort;
      }
#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
      if( IsVirtual(pTab) || pTab->pSelect ){
        i16 nCol;
        if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
................................................................................
  if( pDest->eDest==SRT_EphemTab ){
    sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr);
  }

  /* Set the limiter.
  */
  iEnd = sqlite3VdbeMakeLabel(v);
  if( (p->selFlags & SF_FixedLimit)==0 ){
    p->nSelectRow = 320;  /* 4 billion rows */
  }
  computeLimitRegisters(pParse, p, iEnd);
  if( p->iLimit==0 && sSort.addrSortIndex>=0 ){
    sqlite3VdbeChangeOpcode(v, sSort.addrSortIndex, OP_SorterOpen);
    sSort.sortFlags |= SORTFLAG_UseSorter;
  }

  /* Open an ephemeral index to use for the distinct set.

Changes to src/shell.c.

942
943
944
945
946
947
948



















949
950
951
952
953
954
955
....
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
....
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
....
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
    }
  }
  raw_printf(p->out, "\n");
  return SQLITE_OK;
}
#endif





















/*
** This is the callback routine that the shell
** invokes for each row of a query result.
*/
static int shell_callback(
  void *pArg,
................................................................................
              azArg[i] ? azArg[i] : p->nullValue,
              i==nArg-1 ? rowSep : "  ");
        }
      }
      break;
    }
    case MODE_Semi: {   /* .schema and .fullschema output */
      utf8_printf(p->out, "%s;\n", azArg[0]);
      break;
    }
    case MODE_Pretty: {  /* .schema and .fullschema with --indent */
      char *z;
      int j;
      int nParen = 0;
      char cEnd = 0;
................................................................................
          }else if( c=='[' ){
            cEnd = ']';
          }else if( c=='(' ){
            nParen++;
          }else if( c==')' ){
            nParen--;
            if( nLine>0 && nParen==0 && j>0 ){
              utf8_printf(p->out, "%.*s\n", j, z);
              j = 0;
            }
          }
          z[j++] = c;
          if( nParen==1 && (c=='(' || c==',' || c=='\n') ){
            if( c=='\n' ) j--;
            utf8_printf(p->out, "%.*s\n  ", j, z);
            j = 0;
            nLine++;
            while( IsSpace(z[i+1]) ){ i++; }
          }
        }
        z[j] = 0;
      }
      utf8_printf(p->out, "%s;\n", z);
      sqlite3_free(z);
      break;
    }
    case MODE_List: {
      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          utf8_printf(p->out,"%s%s",azCol[i],
................................................................................
       "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
       "VALUES('table','%q','%q',0,'%q');",
       zTable, zTable, zSql);
    utf8_printf(p->out, "%s\n", zIns);
    sqlite3_free(zIns);
    return 0;
  }else{
    utf8_printf(p->out, "%s;\n", zSql);
  }

  if( strcmp(zType, "table")==0 ){
    sqlite3_stmt *pTableInfo = 0;
    char *zSelect = 0;
    char *zTableInfo = 0;
    char *zTmp = 0;







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







 







|







 







|






|







|







 







|







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
....
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
....
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
....
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
    }
  }
  raw_printf(p->out, "\n");
  return SQLITE_OK;
}
#endif

/*
** Print a schema statement.  Part of MODE_Semi and MODE_Pretty output.
**
** This routine converts some CREATE TABLE statements for shadow tables
** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
*/
static void printSchemaLine(FILE *out, const char *z, const char *zTail){
  if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
    utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
  }else{
    utf8_printf(out, "%s%s", z, zTail);
  }
}
static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
  char c = z[n];
  z[n] = 0;
  printSchemaLine(out, z, zTail);
  z[n] = c;
}

/*
** This is the callback routine that the shell
** invokes for each row of a query result.
*/
static int shell_callback(
  void *pArg,
................................................................................
              azArg[i] ? azArg[i] : p->nullValue,
              i==nArg-1 ? rowSep : "  ");
        }
      }
      break;
    }
    case MODE_Semi: {   /* .schema and .fullschema output */
      printSchemaLine(p->out, azArg[0], ";\n");
      break;
    }
    case MODE_Pretty: {  /* .schema and .fullschema with --indent */
      char *z;
      int j;
      int nParen = 0;
      char cEnd = 0;
................................................................................
          }else if( c=='[' ){
            cEnd = ']';
          }else if( c=='(' ){
            nParen++;
          }else if( c==')' ){
            nParen--;
            if( nLine>0 && nParen==0 && j>0 ){
              printSchemaLineN(p->out, z, j, "\n");
              j = 0;
            }
          }
          z[j++] = c;
          if( nParen==1 && (c=='(' || c==',' || c=='\n') ){
            if( c=='\n' ) j--;
            printSchemaLineN(p->out, z, j, "\n  ");
            j = 0;
            nLine++;
            while( IsSpace(z[i+1]) ){ i++; }
          }
        }
        z[j] = 0;
      }
      printSchemaLine(p->out, z, ";\n");
      sqlite3_free(z);
      break;
    }
    case MODE_List: {
      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          utf8_printf(p->out,"%s%s",azCol[i],
................................................................................
       "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
       "VALUES('table','%q','%q',0,'%q');",
       zTable, zTable, zSql);
    utf8_printf(p->out, "%s\n", zIns);
    sqlite3_free(zIns);
    return 0;
  }else{
    printSchemaLine(p->out, zSql, ";\n");
  }

  if( strcmp(zType, "table")==0 ){
    sqlite3_stmt *pTableInfo = 0;
    char *zSelect = 0;
    char *zTableInfo = 0;
    char *zTmp = 0;

Changes to src/sqliteInt.h.

1797
1798
1799
1800
1801
1802
1803

1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
  Index *pIndex;       /* List of SQL indexes on this table. */
  Select *pSelect;     /* NULL for tables.  Points to definition if a view. */
  FKey *pFKey;         /* Linked list of all foreign keys in this table */
  char *zColAff;       /* String defining the affinity of each column */
  ExprList *pCheck;    /* All CHECK constraints */
                       /*   ... also used as column name list in a VIEW */
  int tnum;            /* Root BTree page for this table */

  i16 iPKey;           /* If not negative, use aCol[iPKey] as the rowid */
  i16 nCol;            /* Number of columns in this table */
  u16 nRef;            /* Number of pointers to this Table */
  LogEst nRowLogEst;   /* Estimated rows in table - from sqlite_stat1 table */
  LogEst szTabRow;     /* Estimated size of each table row in bytes */
#ifdef SQLITE_ENABLE_COSTMULT
  LogEst costMult;     /* Cost multiplier for using this table */
#endif
  u8 tabFlags;         /* Mask of TF_* values */
  u8 keyConf;          /* What to do in case of uniqueness conflict on iPKey */







>


<







1797
1798
1799
1800
1801
1802
1803
1804
1805
1806

1807
1808
1809
1810
1811
1812
1813
  Index *pIndex;       /* List of SQL indexes on this table. */
  Select *pSelect;     /* NULL for tables.  Points to definition if a view. */
  FKey *pFKey;         /* Linked list of all foreign keys in this table */
  char *zColAff;       /* String defining the affinity of each column */
  ExprList *pCheck;    /* All CHECK constraints */
                       /*   ... also used as column name list in a VIEW */
  int tnum;            /* Root BTree page for this table */
  u32 nTabRef;         /* Number of pointers to this Table */
  i16 iPKey;           /* If not negative, use aCol[iPKey] as the rowid */
  i16 nCol;            /* Number of columns in this table */

  LogEst nRowLogEst;   /* Estimated rows in table - from sqlite_stat1 table */
  LogEst szTabRow;     /* Estimated size of each table row in bytes */
#ifdef SQLITE_ENABLE_COSTMULT
  LogEst costMult;     /* Cost multiplier for using this table */
#endif
  u8 tabFlags;         /* Mask of TF_* values */
  u8 keyConf;          /* What to do in case of uniqueness conflict on iPKey */

Changes to src/trigger.c.

304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
...
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
    /* Make an entry in the sqlite_master table */
    v = sqlite3GetVdbe(pParse);
    if( v==0 ) goto triggerfinish_cleanup;
    sqlite3BeginWriteOperation(pParse, 0, iDb);
    z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n);
    sqlite3NestedParse(pParse,
       "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
       db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), zName,
       pTrig->table, z);
    sqlite3DbFree(db, z);
    sqlite3ChangeCookie(pParse, iDb);
    sqlite3VdbeAddParseSchemaOp(v, iDb,
        sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName));
  }

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

  /* Generate code to destroy the database record of the trigger.
  */
  assert( pTable!=0 );
  if( (v = sqlite3GetVdbe(pParse))!=0 ){
    sqlite3NestedParse(pParse,
       "DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'",
       db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pTrigger->zName
    );
    sqlite3ChangeCookie(pParse, iDb);
    sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0);
  }
}

/*







|







 







|







304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
...
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
    /* Make an entry in the sqlite_master table */
    v = sqlite3GetVdbe(pParse);
    if( v==0 ) goto triggerfinish_cleanup;
    sqlite3BeginWriteOperation(pParse, 0, iDb);
    z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n);
    sqlite3NestedParse(pParse,
       "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
       db->aDb[iDb].zDbSName, MASTER_NAME, zName,
       pTrig->table, z);
    sqlite3DbFree(db, z);
    sqlite3ChangeCookie(pParse, iDb);
    sqlite3VdbeAddParseSchemaOp(v, iDb,
        sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName));
  }

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

  /* Generate code to destroy the database record of the trigger.
  */
  assert( pTable!=0 );
  if( (v = sqlite3GetVdbe(pParse))!=0 ){
    sqlite3NestedParse(pParse,
       "DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'",
       db->aDb[iDb].zDbSName, MASTER_NAME, pTrigger->zName
    );
    sqlite3ChangeCookie(pParse, iDb);
    sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0);
  }
}

/*

Changes to src/vdbe.c.

5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
  }
#endif

  iDb = pOp->p1;
  assert( iDb>=0 && iDb<db->nDb );
  assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );
  /* Used to be a conditional */ {
    zMaster = SCHEMA_TABLE(iDb);
    initData.db = db;
    initData.iDb = pOp->p1;
    initData.pzErrMsg = &p->zErrMsg;
    zSql = sqlite3MPrintf(db,
       "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
       db->aDb[iDb].zDbSName, zMaster, pOp->p4.z);
    if( zSql==0 ){







|







5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
  }
#endif

  iDb = pOp->p1;
  assert( iDb>=0 && iDb<db->nDb );
  assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );
  /* Used to be a conditional */ {
    zMaster = MASTER_NAME;
    initData.db = db;
    initData.iDb = pOp->p1;
    initData.pzErrMsg = &p->zErrMsg;
    zSql = sqlite3MPrintf(db,
       "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
       db->aDb[iDb].zDbSName, zMaster, pOp->p4.z);
    if( zSql==0 ){

Changes to src/vtab.c.

404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
....
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
    ** by sqlite3StartTable().
    */
    iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
    sqlite3NestedParse(pParse,
      "UPDATE %Q.%s "
         "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
       "WHERE rowid=#%d",
      db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb),
      pTab->zName,
      pTab->zName,
      zStmt,
      pParse->regRowid
    );
    sqlite3DbFree(db, zStmt);
    v = sqlite3GetVdbe(pParse);
................................................................................
  if( pTab==0 ) return 0;
  pTab->zName = sqlite3DbStrDup(db, pMod->zName);
  if( pTab->zName==0 ){
    sqlite3DbFree(db, pTab);
    return 0;
  }
  pMod->pEpoTab = pTab;
  pTab->nRef = 1;
  pTab->pSchema = db->aDb[0].pSchema;
  pTab->tabFlags |= TF_Virtual;
  pTab->nModuleArg = 0;
  pTab->iPKey = -1;
  addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName));
  addModuleArgument(db, pTab, 0);
  addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName));







|







 







|







404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
....
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
    ** by sqlite3StartTable().
    */
    iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
    sqlite3NestedParse(pParse,
      "UPDATE %Q.%s "
         "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
       "WHERE rowid=#%d",
      db->aDb[iDb].zDbSName, MASTER_NAME,
      pTab->zName,
      pTab->zName,
      zStmt,
      pParse->regRowid
    );
    sqlite3DbFree(db, zStmt);
    v = sqlite3GetVdbe(pParse);
................................................................................
  if( pTab==0 ) return 0;
  pTab->zName = sqlite3DbStrDup(db, pMod->zName);
  if( pTab->zName==0 ){
    sqlite3DbFree(db, pTab);
    return 0;
  }
  pMod->pEpoTab = pTab;
  pTab->nTabRef = 1;
  pTab->pSchema = db->aDb[0].pSchema;
  pTab->tabFlags |= TF_Virtual;
  pTab->nModuleArg = 0;
  pTab->iPKey = -1;
  addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName));
  addModuleArgument(db, pTab, 0);
  addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName));

Changes to test/alter.test.

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
...
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
...
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
    CREATE $::temp TABLE objlist(type, name, tbl_name);
    INSERT INTO objlist SELECT type, name, tbl_name 
        FROM sqlite_master WHERE NAME!='objlist';
  }]
  ifcapable tempdb {
    execsql {
      INSERT INTO objlist SELECT type, name, tbl_name 
          FROM sqlite_temp_master WHERE NAME!='objlist';
    }
  }

  execsql {
    SELECT type, name, tbl_name FROM objlist ORDER BY tbl_name, type desc, name;
  }
} [list \
................................................................................
    db close
    sqlite3 db test.db
    set DB [sqlite3_connection_pointer db]
    execsql {
      CREATE TEMP TABLE objlist(type, name, tbl_name);
      INSERT INTO objlist SELECT type, name, tbl_name FROM sqlite_master;
      INSERT INTO objlist 
          SELECT type, name, tbl_name FROM sqlite_temp_master 
          WHERE NAME!='objlist';
      SELECT type, name, tbl_name FROM objlist 
          ORDER BY tbl_name, type desc, name;
    }
  } [list \
       table -t1-                         -t1-           \
       index t1i1                         -t1-           \
................................................................................
  execsql {
    DROP TABLE tbl3;
  }
} {}
ifcapable tempdb {
  do_test alter-3.3.8 {
    execsql {
      SELECT * FROM sqlite_temp_master WHERE type = 'trigger';
    }
  } {}
}

} ;# ifcapable trigger

# If the build does not include AUTOINCREMENT fields, omit alter-4.*.







|







 







|







 







|







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
...
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
...
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
    CREATE $::temp TABLE objlist(type, name, tbl_name);
    INSERT INTO objlist SELECT type, name, tbl_name 
        FROM sqlite_master WHERE NAME!='objlist';
  }]
  ifcapable tempdb {
    execsql {
      INSERT INTO objlist SELECT type, name, tbl_name 
          FROM temp.sqlite_master WHERE NAME!='objlist';
    }
  }

  execsql {
    SELECT type, name, tbl_name FROM objlist ORDER BY tbl_name, type desc, name;
  }
} [list \
................................................................................
    db close
    sqlite3 db test.db
    set DB [sqlite3_connection_pointer db]
    execsql {
      CREATE TEMP TABLE objlist(type, name, tbl_name);
      INSERT INTO objlist SELECT type, name, tbl_name FROM sqlite_master;
      INSERT INTO objlist 
          SELECT type, name, tbl_name FROM temp.sqlite_master 
          WHERE NAME!='objlist';
      SELECT type, name, tbl_name FROM objlist 
          ORDER BY tbl_name, type desc, name;
    }
  } [list \
       table -t1-                         -t1-           \
       index t1i1                         -t1-           \
................................................................................
  execsql {
    DROP TABLE tbl3;
  }
} {}
ifcapable tempdb {
  do_test alter-3.3.8 {
    execsql {
      SELECT * FROM temp.sqlite_master WHERE type = 'trigger';
    }
  } {}
}

} ;# ifcapable trigger

# If the build does not include AUTOINCREMENT fields, omit alter-4.*.

Changes to test/alter4.test.

40
41
42
43
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
#

do_test alter4-1.1 {
  execsql {
    CREATE TEMP TABLE abc(a, b, c);
    SELECT sql FROM sqlite_temp_master;
  }





} {{CREATE TABLE abc(a, b, c)}}
do_test alter4-1.2 {
  execsql {ALTER TABLE abc ADD d INTEGER;}
  execsql {
    SELECT sql FROM sqlite_temp_master;





  }
} {{CREATE TABLE abc(a, b, c, d INTEGER)}}
do_test alter4-1.3 {
  execsql {ALTER TABLE abc ADD e}
  execsql {
    SELECT sql FROM sqlite_temp_master;





  }
} {{CREATE TABLE abc(a, b, c, d INTEGER, e)}}
do_test alter4-1.4 {
  execsql {
    CREATE TABLE temp.t1(a, b);
    ALTER TABLE t1 ADD c;
    SELECT sql FROM sqlite_temp_master WHERE tbl_name = 't1';
  }





} {{CREATE TABLE t1(a, b, c)}}
do_test alter4-1.5 {
  execsql {
    ALTER TABLE t1 ADD d CHECK (a>d);
    SELECT sql FROM sqlite_temp_master WHERE tbl_name = 't1';
  }
} {{CREATE TABLE t1(a, b, c, d CHECK (a>d))}}







>
>
>
>
>





>
>
>
>
>






>
>
>
>
>








>
>
>
>
>







40
41
42
43
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#

do_test alter4-1.1 {
  execsql {
    CREATE TEMP TABLE abc(a, b, c);
    SELECT sql FROM sqlite_temp_master;
  }
} {{CREATE TABLE abc(a, b, c)}}
do_test alter4-1.1b {
  execsql {
    SELECT sql FROM temp.sqlite_master;
  }
} {{CREATE TABLE abc(a, b, c)}}
do_test alter4-1.2 {
  execsql {ALTER TABLE abc ADD d INTEGER;}
  execsql {
    SELECT sql FROM sqlite_temp_master;
  }
} {{CREATE TABLE abc(a, b, c, d INTEGER)}}
do_test alter4-1.2b {
  execsql {
    SELECT sql FROM temp.sqlite_master;
  }
} {{CREATE TABLE abc(a, b, c, d INTEGER)}}
do_test alter4-1.3 {
  execsql {ALTER TABLE abc ADD e}
  execsql {
    SELECT sql FROM sqlite_temp_master;
  }
} {{CREATE TABLE abc(a, b, c, d INTEGER, e)}}
do_test alter4-1.3b {
  execsql {
    SELECT sql FROM temp.sqlite_master;
  }
} {{CREATE TABLE abc(a, b, c, d INTEGER, e)}}
do_test alter4-1.4 {
  execsql {
    CREATE TABLE temp.t1(a, b);
    ALTER TABLE t1 ADD c;
    SELECT sql FROM sqlite_temp_master WHERE tbl_name = 't1';
  }
} {{CREATE TABLE t1(a, b, c)}}
do_test alter4-1.4b {
  execsql {
    SELECT sql FROM temp.sqlite_master WHERE tbl_name = 't1';
  }
} {{CREATE TABLE t1(a, b, c)}}
do_test alter4-1.5 {
  execsql {
    ALTER TABLE t1 ADD d CHECK (a>d);
    SELECT sql FROM sqlite_temp_master WHERE tbl_name = 't1';
  }
} {{CREATE TABLE t1(a, b, c, d CHECK (a>d))}}

Changes to test/attach.test.

189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
ifcapable schema_pragmas {
do_test attach-1.20.2 {
  db_list db
} {0 main 2 db2 3 db3 4 db4 5 db6 6 db7 7 db8 8 db9 9 db10 10 db11}
} ;# ifcapable schema_pragmas
integrity_check attach-1.20.3
ifcapable tempdb {
  execsql {select * from sqlite_temp_master}
}
do_test attach-1.21 {
  catchsql {
    ATTACH 'test.db' as db12;
  }
} {0 {}}
if {$SQLITE_MAX_ATTACHED==10} {







|







189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
ifcapable schema_pragmas {
do_test attach-1.20.2 {
  db_list db
} {0 main 2 db2 3 db3 4 db4 5 db6 6 db7 7 db8 8 db9 9 db10 10 db11}
} ;# ifcapable schema_pragmas
integrity_check attach-1.20.3
ifcapable tempdb {
  execsql {select * from temp.sqlite_master}
}
do_test attach-1.21 {
  catchsql {
    ATTACH 'test.db' as db12;
  }
} {0 {}}
if {$SQLITE_MAX_ATTACHED==10} {

Changes to test/attach3.test.

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
  do_test attach3-9.0 {
    execsql {
      CREATE TABLE main.t4(a, b, c);
      CREATE TABLE aux.t4(a, b, c);
      CREATE TEMP TRIGGER tst_trigger BEFORE INSERT ON aux.t4 BEGIN 
        SELECT 'hello world';
      END;
      SELECT count(*) FROM sqlite_temp_master;
    }
  } {1}
  do_test attach3-9.1 {
    execsql {
      DROP TABLE main.t4;
      SELECT count(*) FROM sqlite_temp_master;
    }
  } {1}
  do_test attach3-9.2 {
    execsql {
      DROP TABLE aux.t4;
      SELECT count(*) FROM sqlite_temp_master;
    }
  } {0}
}
} ;# endif trigger

# Make sure the aux.sqlite_master table is read-only
do_test attach3-10.0 {







|











|







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
  do_test attach3-9.0 {
    execsql {
      CREATE TABLE main.t4(a, b, c);
      CREATE TABLE aux.t4(a, b, c);
      CREATE TEMP TRIGGER tst_trigger BEFORE INSERT ON aux.t4 BEGIN 
        SELECT 'hello world';
      END;
      SELECT count(*) FROM temp.sqlite_master;
    }
  } {1}
  do_test attach3-9.1 {
    execsql {
      DROP TABLE main.t4;
      SELECT count(*) FROM sqlite_temp_master;
    }
  } {1}
  do_test attach3-9.2 {
    execsql {
      DROP TABLE aux.t4;
      SELECT count(*) FROM temp.sqlite_master;
    }
  } {0}
}
} ;# endif trigger

# Make sure the aux.sqlite_master table is read-only
do_test attach3-10.0 {

Changes to test/auth.test.

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
...
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
...
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
...
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
...
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
....
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
....
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
....
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
....
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
....
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
....
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
....
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
....
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
....
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
....
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
....
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
....
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
....
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
        return SQLITE_DENY
      }
      return SQLITE_OK
    }
    catchsql {CREATE TEMP TABLE t1(a,b,c)}
  } {1 {not authorized}}
  do_test auth-1.6 {
    execsql {SELECT name FROM sqlite_temp_master}
  } {}
  do_test auth-1.7.1 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_CREATE_TEMP_TABLE"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_DENY
      }
................................................................................
        return SQLITE_IGNORE
      }
      return SQLITE_OK
    }
    catchsql {CREATE TEMP TABLE t1(a,b,c)}
  } {0 {}}
  do_test auth-1.14 {
    execsql {SELECT name FROM sqlite_temp_master}
  } {}
  do_test auth-1.15 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_CREATE_TEMP_TABLE"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_IGNORE
      }
................................................................................
         return SQLITE_IGNORE
      }
      return SQLITE_OK
    }
    catchsql {DROP TABLE t1}
  } {0 {}}
  do_test auth-1.78 {
    execsql {SELECT name FROM sqlite_temp_master}
  } {t1}
}

# Test cases auth-1.79 to auth-1.124 test creating and dropping views.
# Omit these if the library was compiled with views omitted.
ifcapable view {
do_test auth-1.79 {
................................................................................
    }
    catchsql {CREATE TEMPORARY VIEW v1 AS SELECT a+1,b+1 FROM t2}
  } {0 {}}
  do_test auth-1.89 {
    set ::authargs
  } {v1 {} temp {}}
  do_test auth-1.90 {
    execsql {SELECT name FROM sqlite_temp_master}
  } {t1}
}

do_test auth-1.91 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_INSERT" && $arg1=="sqlite_master"} {
      return SQLITE_DENY
................................................................................
    }
    catchsql {
      CREATE TEMP VIEW v1 AS SELECT a+1,b+1 FROM t1;
      DROP VIEW v1
    }
  } {1 {not authorized}}
  do_test auth-1.113 {
    execsql {SELECT name FROM sqlite_temp_master}
  } {t1 v1}
  do_test auth-1.114 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_DROP_TEMP_VIEW"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_DENY
      }
................................................................................
    }
    catchsql {DROP VIEW v1}
  } {0 {}}
  do_test auth-1.120 {
    set ::authargs
  } {v1 {} temp {}}
  do_test auth-1.121 {
    execsql {SELECT name FROM sqlite_temp_master}
  } {t1 v1}
  do_test auth-1.122 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_DROP_TEMP_VIEW"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_OK
      }
................................................................................
    END;
  }
} {1 {not authorized}}
do_test auth-1.139 {
  set ::authargs
} {r1 t1 temp {}}
do_test auth-1.140 {
  execsql {SELECT name FROM sqlite_temp_master}
} {t1}
do_test auth-1.141 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
      return SQLITE_DENY
    }
    return SQLITE_OK
................................................................................
    END;
  }
} {0 {}}
do_test auth-1.144 {
  set ::authargs
} {r1 t1 temp {}}
do_test auth-1.145 {
  execsql {SELECT name FROM sqlite_temp_master}
} {t1}
do_test auth-1.146 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
      return SQLITE_IGNORE
    }
    return SQLITE_OK
................................................................................
    END;
  }
} {0 {}}
do_test auth-1.149 {
  set ::authargs
} {r1 t1 temp {}}
do_test auth-1.150 {
  execsql {SELECT name FROM sqlite_temp_master}
} {t1 r1}

do_test auth-1.151 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
      return SQLITE_DENY
    }
................................................................................
      return SQLITE_DENY
    }
    return SQLITE_OK
  }
  catchsql {DROP TRIGGER r1}
} {1 {not authorized}}
do_test auth-1.165 {
  execsql {SELECT name FROM sqlite_temp_master}
} {t1 r1}
do_test auth-1.166 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_DROP_TEMP_TRIGGER"} {
      set ::authargs [list $arg1 $arg2 $arg3 $arg4]
      return SQLITE_DENY
    }
................................................................................
      return SQLITE_IGNORE
    }
    return SQLITE_OK
  }
  catchsql {DROP TRIGGER r1}
} {0 {}}
do_test auth-1.170 {
  execsql {SELECT name FROM sqlite_temp_master}
} {t1 r1}
do_test auth-1.171 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_DROP_TEMP_TRIGGER"} {
      set ::authargs [list $arg1 $arg2 $arg3 $arg4]
      return SQLITE_IGNORE
    }
................................................................................
  }
  catchsql {DROP TRIGGER r1}
} {0 {}}
do_test auth-1.175 {
  set ::authargs
} {r1 t1 temp {}}
do_test auth-1.176 {
  execsql {SELECT name FROM sqlite_temp_master}
} {t1}
} ;# ifcapable trigger

do_test auth-1.177 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_CREATE_INDEX"} {
      set ::authargs [list $arg1 $arg2 $arg3 $arg4]
................................................................................
        return SQLITE_DENY
      }
      return SQLITE_OK
    }
    catchsql {CREATE INDEX i1 ON t1(b)}
  } {1 {not authorized}}
  do_test auth-1.194 {
    execsql {SELECT name FROM sqlite_temp_master}
  } {t1}
  do_test auth-1.195 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_CREATE_TEMP_INDEX"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_IGNORE
      }
................................................................................
    }
    catchsql {CREATE INDEX i1 ON t1(a)}
  } {0 {}}
  do_test auth-1.201 {
    set ::authargs
  } {i1 t1 temp {}}
  do_test auth-1.202 {
    execsql {SELECT name FROM sqlite_temp_master}
  } {t1 i1}
}

do_test auth-1.203 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
      return SQLITE_DENY
................................................................................
        return SQLITE_IGNORE
      }
      return SQLITE_OK
    }
    catchsql {DROP INDEX i1}
  } {0 {}}
  do_test auth-1.222 {
    execsql {SELECT name FROM sqlite_temp_master}
  } {t1 i1}
  do_test auth-1.223 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_DROP_TEMP_INDEX"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_IGNORE
      }
................................................................................
    }
    catchsql {DROP INDEX i1}
  } {0 {}}
  do_test auth-1.224 {
    set ::authargs
  } {i1 t1 temp {}}
  do_test auth-1.225 {
    execsql {SELECT name FROM sqlite_temp_master}
  } {t1 i1}
  do_test auth-1.226 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_DROP_TEMP_INDEX"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_OK
      }
................................................................................
    }
    catchsql {DROP INDEX i1}
  } {0 {}}
  do_test auth-1.227 {
    set ::authargs
  } {i1 t1 temp {}}
  do_test auth-1.228 {
    execsql {SELECT name FROM sqlite_temp_master}
  } {t1}
}

do_test auth-1.229 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_PRAGMA"} {
      set ::authargs [list $arg1 $arg2 $arg3 $arg4]
................................................................................
          return SQLITE_OK
        }
        catchsql {
          ALTER TABLE t1x RENAME TO t1
        }
      } {0 {}}
      do_test auth-1.267 {
        execsql {SELECT name FROM sqlite_temp_master WHERE type='table'}
      } {t1x}
      do_test auth-1.268 {
        set authargs
      } {temp t1x {} {}}
      do_test auth-1.269 {
        proc auth {code arg1 arg2 arg3 arg4 args} {
          if {$code=="SQLITE_ALTER_TABLE"} {
................................................................................
      return SQLITE_OK
    }
    catchsql {
      ALTER TABLE t5 ADD COLUMN new_col_3
    }
  } {1 {not authorized}}
  do_test auth-1.307 {
    set x [execsql {SELECT sql FROM sqlite_temp_master WHERE type='t5'}]
    regexp new_col_3 $x
  } {0}

  do_test auth-1.308 {
    set authargs
  } {main t5 {} {}}
  execsql {DROP TABLE t5}
................................................................................
    } else {
      set stat4 ""
    }
  }
  do_test auth-5.2 {
    execsql {
      SELECT name FROM (
        SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master)
      WHERE type='table'
      ORDER BY name
    }
  } "sqlite_stat1 ${stat4}t1 t2 t3 t4"
}

# Ticket #3944







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
...
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
...
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
...
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
...
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
....
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
....
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
....
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
....
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
....
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
....
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
....
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
....
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
....
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
....
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
....
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
....
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
....
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
        return SQLITE_DENY
      }
      return SQLITE_OK
    }
    catchsql {CREATE TEMP TABLE t1(a,b,c)}
  } {1 {not authorized}}
  do_test auth-1.6 {
    execsql {SELECT name FROM temp.sqlite_master}
  } {}
  do_test auth-1.7.1 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_CREATE_TEMP_TABLE"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_DENY
      }
................................................................................
        return SQLITE_IGNORE
      }
      return SQLITE_OK
    }
    catchsql {CREATE TEMP TABLE t1(a,b,c)}
  } {0 {}}
  do_test auth-1.14 {
    execsql {SELECT name FROM temp.sqlite_master}
  } {}
  do_test auth-1.15 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_CREATE_TEMP_TABLE"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_IGNORE
      }
................................................................................
         return SQLITE_IGNORE
      }
      return SQLITE_OK
    }
    catchsql {DROP TABLE t1}
  } {0 {}}
  do_test auth-1.78 {
    execsql {SELECT name FROM temp.sqlite_master}
  } {t1}
}

# Test cases auth-1.79 to auth-1.124 test creating and dropping views.
# Omit these if the library was compiled with views omitted.
ifcapable view {
do_test auth-1.79 {
................................................................................
    }
    catchsql {CREATE TEMPORARY VIEW v1 AS SELECT a+1,b+1 FROM t2}
  } {0 {}}
  do_test auth-1.89 {
    set ::authargs
  } {v1 {} temp {}}
  do_test auth-1.90 {
    execsql {SELECT name FROM temp.sqlite_master}
  } {t1}
}

do_test auth-1.91 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_INSERT" && $arg1=="sqlite_master"} {
      return SQLITE_DENY
................................................................................
    }
    catchsql {
      CREATE TEMP VIEW v1 AS SELECT a+1,b+1 FROM t1;
      DROP VIEW v1
    }
  } {1 {not authorized}}
  do_test auth-1.113 {
    execsql {SELECT name FROM temp.sqlite_master}
  } {t1 v1}
  do_test auth-1.114 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_DROP_TEMP_VIEW"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_DENY
      }
................................................................................
    }
    catchsql {DROP VIEW v1}
  } {0 {}}
  do_test auth-1.120 {
    set ::authargs
  } {v1 {} temp {}}
  do_test auth-1.121 {
    execsql {SELECT name FROM temp.sqlite_master}
  } {t1 v1}
  do_test auth-1.122 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_DROP_TEMP_VIEW"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_OK
      }
................................................................................
    END;
  }
} {1 {not authorized}}
do_test auth-1.139 {
  set ::authargs
} {r1 t1 temp {}}
do_test auth-1.140 {
  execsql {SELECT name FROM temp.sqlite_master}
} {t1}
do_test auth-1.141 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
      return SQLITE_DENY
    }
    return SQLITE_OK
................................................................................
    END;
  }
} {0 {}}
do_test auth-1.144 {
  set ::authargs
} {r1 t1 temp {}}
do_test auth-1.145 {
  execsql {SELECT name FROM temp.sqlite_master}
} {t1}
do_test auth-1.146 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
      return SQLITE_IGNORE
    }
    return SQLITE_OK
................................................................................
    END;
  }
} {0 {}}
do_test auth-1.149 {
  set ::authargs
} {r1 t1 temp {}}
do_test auth-1.150 {
  execsql {SELECT name FROM temp.sqlite_master}
} {t1 r1}

do_test auth-1.151 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
      return SQLITE_DENY
    }
................................................................................
      return SQLITE_DENY
    }
    return SQLITE_OK
  }
  catchsql {DROP TRIGGER r1}
} {1 {not authorized}}
do_test auth-1.165 {
  execsql {SELECT name FROM temp.sqlite_master}
} {t1 r1}
do_test auth-1.166 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_DROP_TEMP_TRIGGER"} {
      set ::authargs [list $arg1 $arg2 $arg3 $arg4]
      return SQLITE_DENY
    }
................................................................................
      return SQLITE_IGNORE
    }
    return SQLITE_OK
  }
  catchsql {DROP TRIGGER r1}
} {0 {}}
do_test auth-1.170 {
  execsql {SELECT name FROM temp.sqlite_master}
} {t1 r1}
do_test auth-1.171 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_DROP_TEMP_TRIGGER"} {
      set ::authargs [list $arg1 $arg2 $arg3 $arg4]
      return SQLITE_IGNORE
    }
................................................................................
  }
  catchsql {DROP TRIGGER r1}
} {0 {}}
do_test auth-1.175 {
  set ::authargs
} {r1 t1 temp {}}
do_test auth-1.176 {
  execsql {SELECT name FROM temp.sqlite_master}
} {t1}
} ;# ifcapable trigger

do_test auth-1.177 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_CREATE_INDEX"} {
      set ::authargs [list $arg1 $arg2 $arg3 $arg4]
................................................................................
        return SQLITE_DENY
      }
      return SQLITE_OK
    }
    catchsql {CREATE INDEX i1 ON t1(b)}
  } {1 {not authorized}}
  do_test auth-1.194 {
    execsql {SELECT name FROM temp.sqlite_master}
  } {t1}
  do_test auth-1.195 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_CREATE_TEMP_INDEX"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_IGNORE
      }
................................................................................
    }
    catchsql {CREATE INDEX i1 ON t1(a)}
  } {0 {}}
  do_test auth-1.201 {
    set ::authargs
  } {i1 t1 temp {}}
  do_test auth-1.202 {
    execsql {SELECT name FROM temp.sqlite_master}
  } {t1 i1}
}

do_test auth-1.203 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
      return SQLITE_DENY
................................................................................
        return SQLITE_IGNORE
      }
      return SQLITE_OK
    }
    catchsql {DROP INDEX i1}
  } {0 {}}
  do_test auth-1.222 {
    execsql {SELECT name FROM temp.sqlite_master}
  } {t1 i1}
  do_test auth-1.223 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_DROP_TEMP_INDEX"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_IGNORE
      }
................................................................................
    }
    catchsql {DROP INDEX i1}
  } {0 {}}
  do_test auth-1.224 {
    set ::authargs
  } {i1 t1 temp {}}
  do_test auth-1.225 {
    execsql {SELECT name FROM temp.sqlite_master}
  } {t1 i1}
  do_test auth-1.226 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_DROP_TEMP_INDEX"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_OK
      }
................................................................................
    }
    catchsql {DROP INDEX i1}
  } {0 {}}
  do_test auth-1.227 {
    set ::authargs
  } {i1 t1 temp {}}
  do_test auth-1.228 {
    execsql {SELECT name FROM temp.sqlite_master}
  } {t1}
}

do_test auth-1.229 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_PRAGMA"} {
      set ::authargs [list $arg1 $arg2 $arg3 $arg4]
................................................................................
          return SQLITE_OK
        }
        catchsql {
          ALTER TABLE t1x RENAME TO t1
        }
      } {0 {}}
      do_test auth-1.267 {
        execsql {SELECT name FROM temp.sqlite_master WHERE type='table'}
      } {t1x}
      do_test auth-1.268 {
        set authargs
      } {temp t1x {} {}}
      do_test auth-1.269 {
        proc auth {code arg1 arg2 arg3 arg4 args} {
          if {$code=="SQLITE_ALTER_TABLE"} {
................................................................................
      return SQLITE_OK
    }
    catchsql {
      ALTER TABLE t5 ADD COLUMN new_col_3
    }
  } {1 {not authorized}}
  do_test auth-1.307 {
    set x [execsql {SELECT sql FROM temp.sqlite_master WHERE type='t5'}]
    regexp new_col_3 $x
  } {0}

  do_test auth-1.308 {
    set authargs
  } {main t5 {} {}}
  execsql {DROP TABLE t5}
................................................................................
    } else {
      set stat4 ""
    }
  }
  do_test auth-5.2 {
    execsql {
      SELECT name FROM (
        SELECT * FROM sqlite_master UNION ALL SELECT * FROM temp.sqlite_master)
      WHERE type='table'
      ORDER BY name
    }
  } "sqlite_stat1 ${stat4}t1 t2 t3 t4"
}

# Ticket #3944

Changes to test/auth3.test.

118
119
120
121
122
123
124
125
126
127
128
  return SQLITE_OK
}
do_execsql_test auth3-3.0 {
  CREATE TEMPORARY TABLE TempTable (
      key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,
      value TEXT NOT NULL ON CONFLICT FAIL);
  ALTER TABLE TempTable RENAME TO DoNotRead;
  SELECT name FROM sqlite_temp_master;
} {DoNotRead sqlite_autoindex_DoNotRead_1}

finish_test







|



118
119
120
121
122
123
124
125
126
127
128
  return SQLITE_OK
}
do_execsql_test auth3-3.0 {
  CREATE TEMPORARY TABLE TempTable (
      key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,
      value TEXT NOT NULL ON CONFLICT FAIL);
  ALTER TABLE TempTable RENAME TO DoNotRead;
  SELECT name FROM temp.sqlite_master;
} {DoNotRead sqlite_autoindex_DoNotRead_1}

finish_test

Changes to test/autoinc.test.

340
341
342
343
344
345
346
347
348
349
350
351
352
353
354

# AUTOINCREMENT on TEMP tables.
#
ifcapable tempdb {
  do_test autoinc-4.1 {
    execsql {
      SELECT 1, name FROM sqlite_master WHERE type='table';
      SELECT 2, name FROM sqlite_temp_master WHERE type='table';
    }
  } {1 sqlite_sequence}
  do_test autoinc-4.2 {
    execsql {
      CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y);
      CREATE TEMP TABLE t3(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
      SELECT 1, name FROM sqlite_master WHERE type='table';







|







340
341
342
343
344
345
346
347
348
349
350
351
352
353
354

# AUTOINCREMENT on TEMP tables.
#
ifcapable tempdb {
  do_test autoinc-4.1 {
    execsql {
      SELECT 1, name FROM sqlite_master WHERE type='table';
      SELECT 2, name FROM temp.sqlite_master WHERE type='table';
    }
  } {1 sqlite_sequence}
  do_test autoinc-4.2 {
    execsql {
      CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y);
      CREATE TEMP TABLE t3(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
      SELECT 1, name FROM sqlite_master WHERE type='table';

Changes to test/bestindex3.test.

168
169
170
171
172
173
174
175
  }
}

do_execsql_test 3.1 { CREATE VIRTUAL TABLE t3 USING tcl('vvv_command') }
do_execsql_test 3.2 { CREATE VIRTUAL TABLE t4 USING tcl('yyy_command') }

finish_test








<
168
169
170
171
172
173
174

  }
}

do_execsql_test 3.1 { CREATE VIRTUAL TABLE t3 USING tcl('vvv_command') }
do_execsql_test 3.2 { CREATE VIRTUAL TABLE t4 USING tcl('yyy_command') }

finish_test

Changes to test/bestindex4.test.

114
115
116
117
118
119
120
121
      }
    }

  }
}

finish_test








<
114
115
116
117
118
119
120

      }
    }

  }
}

finish_test

Changes to test/e_dropview.test.

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  }
}

proc list_all_views {{db db}} {
  set res [list]
  $db eval { PRAGMA database_list } {
    set tbl "$name.sqlite_master"
    if {$name == "temp"} { set tbl sqlite_temp_master }

    set sql "SELECT '$name.' || name FROM $tbl WHERE type = 'view'"
    lappend res {*}[$db eval $sql]
  }
  set res
}








|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  }
}

proc list_all_views {{db db}} {
  set res [list]
  $db eval { PRAGMA database_list } {
    set tbl "$name.sqlite_master"
    if {$name == "temp"} { set tbl temp.sqlite_master }

    set sql "SELECT '$name.' || name FROM $tbl WHERE type = 'view'"
    lappend res {*}[$db eval $sql]
  }
  set res
}

Changes to test/fkey1.test.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
...
180
181
182
183
184
185
186
187





















188
# This file implements regression tests for SQLite library.
#
# This file implements tests for foreign keys.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl


ifcapable {!foreignkey} {
  finish_test
  return
}

# Create a table and some data to work with.
................................................................................
  INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (2, 1, 'A-2-1');
  INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (3, 2, 'A-3-2');
  INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (4, 3, 'A-4-3');
}
do_catchsql_test fkey1-5.4 {
  INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (2, 3, 'A-2-3');
} {1 {FOREIGN KEY constraint failed}}






















finish_test







>







 








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

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# This file implements regression tests for SQLite library.
#
# This file implements tests for foreign keys.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fkey1

ifcapable {!foreignkey} {
  finish_test
  return
}

# Create a table and some data to work with.
................................................................................
  INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (2, 1, 'A-2-1');
  INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (3, 2, 'A-3-2');
  INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (4, 3, 'A-4-3');
}
do_catchsql_test fkey1-5.4 {
  INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (2, 3, 'A-2-3');
} {1 {FOREIGN KEY constraint failed}}

#-------------------------------------------------------------------------
# Check that foreign key processing is not fooled by partial indexes
# on the parent table.
#
do_execsql_test 6.0 {
  CREATE TABLE p1(x, y);
  CREATE UNIQUE INDEX p1x ON p1(x) WHERE y<2;
  INSERT INTO p1 VALUES(1, 1);
  CREATE TABLE c1(a REFERENCES p1(x));
}

do_catchsql_test 6.1 {
  INSERT INTO c1 VALUES(1);
} {1 {foreign key mismatch - "c1" referencing "p1"}}

do_execsql_test 6.2 {
  CREATE UNIQUE INDEX p1x2 ON p1(x);
  INSERT INTO c1 VALUES(1);
} {}


finish_test

Changes to test/fkey2.test.

1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
....
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
    catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 }
  } {1 {Cannot add a REFERENCES column with non-NULL default value}}
  do_test fkey2-14.1tmp.6 {
    execsql { 
      PRAGMA foreign_keys = off;
      ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
      PRAGMA foreign_keys = on;
      SELECT sql FROM sqlite_temp_master WHERE name='t2';
    }
  } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}

  do_test fkey2-14.2tmp.1.1 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
  } {{CREATE TABLE t1(a REFERENCES "t3")}}
  do_test fkey2-14.2tmp.1.2 {
................................................................................
  } [list \
    {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1)}                     \
    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)}    \
    {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)}  \
  ]
  do_test fkey2-14.2tmp.2.2 {
    execsql { ALTER TABLE t1 RENAME TO t4 }
    execsql { SELECT sql FROM sqlite_temp_master WHERE type = 'table'}
  } [list \
    {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4")}                    \
    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)}     \
    {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \
  ]
  do_test fkey2-14.2tmp.2.3 {
    catchsql { INSERT INTO t3 VALUES(1, 2, 3) }







|







 







|







1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
....
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
    catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 }
  } {1 {Cannot add a REFERENCES column with non-NULL default value}}
  do_test fkey2-14.1tmp.6 {
    execsql { 
      PRAGMA foreign_keys = off;
      ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
      PRAGMA foreign_keys = on;
      SELECT sql FROM temp.sqlite_master WHERE name='t2';
    }
  } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}

  do_test fkey2-14.2tmp.1.1 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
  } {{CREATE TABLE t1(a REFERENCES "t3")}}
  do_test fkey2-14.2tmp.1.2 {
................................................................................
  } [list \
    {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1)}                     \
    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)}    \
    {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)}  \
  ]
  do_test fkey2-14.2tmp.2.2 {
    execsql { ALTER TABLE t1 RENAME TO t4 }
    execsql { SELECT sql FROM temp.sqlite_master WHERE type = 'table'}
  } [list \
    {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4")}                    \
    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)}     \
    {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \
  ]
  do_test fkey2-14.2tmp.2.3 {
    catchsql { INSERT INTO t3 VALUES(1, 2, 3) }

Changes to test/incrblob4.test.

103
104
105
106
107
108
109
110
} {1 {database table is locked}}
do_test 4.4 {
  sqlite3_extended_errcode db
} {SQLITE_LOCKED}
close $blob

finish_test








<
103
104
105
106
107
108
109

} {1 {database table is locked}}
do_test 4.4 {
  sqlite3_extended_errcode db
} {SQLITE_LOCKED}
close $blob

finish_test

Changes to test/intarray.test.

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

do_test intarray-1.1 {
  set ia1 [sqlite3_intarray_create db ia1]
  set ia2 [sqlite3_intarray_create db ia2]
  set ia3 [sqlite3_intarray_create db ia3]
  set ia4 [sqlite3_intarray_create db ia4]
  db eval {
    SELECT type, name FROM sqlite_temp_master
     ORDER BY name
  }
} {table ia1 table ia2 table ia3 table ia4}

do_test intarray-1.2 {
  db eval {
    SELECT b FROM t1 WHERE a IN ia3 ORDER BY a







|







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

do_test intarray-1.1 {
  set ia1 [sqlite3_intarray_create db ia1]
  set ia2 [sqlite3_intarray_create db ia2]
  set ia3 [sqlite3_intarray_create db ia3]
  set ia4 [sqlite3_intarray_create db ia4]
  db eval {
    SELECT type, name FROM temp.sqlite_master
     ORDER BY name
  }
} {table ia1 table ia2 table ia3 table ia4}

do_test intarray-1.2 {
  db eval {
    SELECT b FROM t1 WHERE a IN ia3 ORDER BY a

Changes to test/interrupt.test.

124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
      set ::sqlite_interrupt_count $::i
      catchsql {
        INSERT INTO t2 SELECT * FROM t1;
      }
    } {1 interrupted}
    do_test interrupt-3.$i.3 {
      execsql {
        SELECT name FROM sqlite_temp_master;
      }
    } {}
    do_test interrupt-3.$i.4 {
      catchsql {
        ROLLBACK
      }
    } {1 {cannot rollback - no transaction is active}}
    do_test interrupt-3.$i.5 {
      catchsql {SELECT name FROM sqlite_temp_master};
      execsql {
        SELECT name FROM sqlite_temp_master;
      }
    } {}
  }
}

# There are reports of a memory leak if an interrupt occurs during
# the beginning of a complex query - before the first callback.  We







|










|







124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
      set ::sqlite_interrupt_count $::i
      catchsql {
        INSERT INTO t2 SELECT * FROM t1;
      }
    } {1 interrupted}
    do_test interrupt-3.$i.3 {
      execsql {
        SELECT name FROM temp.sqlite_master;
      }
    } {}
    do_test interrupt-3.$i.4 {
      catchsql {
        ROLLBACK
      }
    } {1 {cannot rollback - no transaction is active}}
    do_test interrupt-3.$i.5 {
      catchsql {SELECT name FROM sqlite_temp_master};
      execsql {
        SELECT name FROM temp.sqlite_master;
      }
    } {}
  }
}

# There are reports of a memory leak if an interrupt occurs during
# the beginning of a complex query - before the first callback.  We

Changes to test/regexp2.test.

118
119
120
121
122
123
124
125

  DELETE FROM t5;
  SELECT * FROM t6;
} {eab dea}


finish_test








<
118
119
120
121
122
123
124


  DELETE FROM t5;
  SELECT * FROM t6;
} {eab dea}


finish_test

Changes to test/rowvalue.test.

313
314
315
316
317
318
319
320
321
    set err "sub-select returns $n columns - expected 1"
  }
  do_catchsql_test 14.2.$tn $sql [list 1 $err]
}


finish_test









<
<
313
314
315
316
317
318
319


    set err "sub-select returns $n columns - expected 1"
  }
  do_catchsql_test 14.2.$tn $sql [list 1 $err]
}


finish_test


Changes to test/rowvalue9.test.

295
296
297
298
299
300
301
302
  SELECT * FROM g2 WHERE (x, y) IN (
    SELECT a, b FROM g1 ORDER BY 1, 2 LIMIT 10
  );
} { 1 4 1 5 }


finish_test








<
295
296
297
298
299
300
301

  SELECT * FROM g2 WHERE (x, y) IN (
    SELECT a, b FROM g1 ORDER BY 1, 2 LIMIT 10
  );
} { 1 4 1 5 }


finish_test

Changes to test/rowvaluefault.test.

65
66
67
68
69
70
71
72
    SELECT fou FROM xyz 
    WHERE (one, two, thr) BETWEEN ('B', 'B', 'B') AND ('C', 'C', 'C') }
} -test {
  faultsim_test_result {0 {2 3}} 
}

finish_test








<
65
66
67
68
69
70
71

    SELECT fou FROM xyz 
    WHERE (one, two, thr) BETWEEN ('B', 'B', 'B') AND ('C', 'C', 'C') }
} -test {
  faultsim_test_result {0 {2 3}} 
}

finish_test

Changes to test/schema4.test.

145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
    END;

    CREATE TEMP TABLE x1(x);
    INSERT INTO x1 VALUES(123);
  } {}

  do_execsql_test schema4-2.8 {
    select sql from sqlite_temp_master WHERE type='table';
  } {{CREATE TABLE x1(x)}}

  do_execsql_test schema4-2.7 { ALTER TABLE tbl RENAME TO tbl2 } {}

  do_execsql_test schema4-2.9 {
    select sql from sqlite_temp_master WHERE type='table';
  } {{CREATE TABLE x1(x)}}







|







145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
    END;

    CREATE TEMP TABLE x1(x);
    INSERT INTO x1 VALUES(123);
  } {}

  do_execsql_test schema4-2.8 {
    select sql from temp.sqlite_master WHERE type='table';
  } {{CREATE TABLE x1(x)}}

  do_execsql_test schema4-2.7 { ALTER TABLE tbl RENAME TO tbl2 } {}

  do_execsql_test schema4-2.9 {
    select sql from sqlite_temp_master WHERE type='table';
  } {{CREATE TABLE x1(x)}}

Changes to test/snapshot2.test.

194
195
196
197
198
199
200
201
202
  execsql {
    PRAGMA aux.journal_mode = delete;
  }
  list [catch { sqlite3_snapshot_recover db aux } msg] $msg
} {1 SQLITE_ERROR}

finish_test









<
<
194
195
196
197
198
199
200


  execsql {
    PRAGMA aux.journal_mode = delete;
  }
  list [catch { sqlite3_snapshot_recover db aux } msg] $msg
} {1 SQLITE_ERROR}

finish_test


Changes to test/speedtest1.c.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
....
1377
1378
1379
1380
1381
1382
1383

1384
1385
1386
1387
1388
1389
1390
....
1439
1440
1441
1442
1443
1444
1445





1446
1447
1448
1449
1450
1451
1452
....
1569
1570
1571
1572
1573
1574
1575



1576
1577
1578
1579
1580
1581
1582
  "  --exclusive         Enable locking_mode=EXCLUSIVE\n"
  "  --explain           Like --sqlonly but with added EXPLAIN keywords\n"
  "  --heap SZ MIN       Memory allocator uses SZ bytes & min allocation MIN\n"
  "  --incrvacuum        Enable incremenatal vacuum mode\n"
  "  --journal M         Set the journal_mode to M\n"
  "  --key KEY           Set the encryption key to KEY\n"
  "  --lookaside N SZ    Configure lookaside for N slots of SZ bytes each\n"

  "  --multithread       Set multithreaded mode\n"
  "  --nomemstat         Disable memory statistics\n"
  "  --nosync            Set PRAGMA synchronous=OFF\n"
  "  --notnull           Add NOT NULL constraints to table columns\n"
  "  --pagesize N        Set the page size to N\n"
  "  --pcache N SZ       Configure N pages of pagecache each of size SZ bytes\n"
  "  --primarykey        Use PRIMARY KEY instead of UNIQUE where appropriate\n"
................................................................................
  int noSync = 0;               /* True for --nosync */
  int pageSize = 0;             /* Desired page size.  0 means default */
  int nPCache = 0, szPCache = 0;/* --pcache configuration */
  int doPCache = 0;             /* True if --pcache is seen */
  int nScratch = 0, szScratch=0;/* --scratch configuration */
  int showStats = 0;            /* True for --stats */
  int nThread = 0;              /* --threads value */

  const char *zTSet = "main";   /* Which --testset torun */
  int doTrace = 0;              /* True for --trace */
  const char *zEncoding = 0;    /* --utf16be or --utf16le */
  const char *zDbName = 0;      /* Name of the test database */

  void *pHeap = 0;              /* Allocated heap space */
  void *pLook = 0;              /* Allocated lookaside space */
................................................................................
        i += 2;
#if SQLITE_VERSION_NUMBER>=3006000
      }else if( strcmp(z,"multithread")==0 ){
        sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
      }else if( strcmp(z,"nomemstat")==0 ){
        sqlite3_config(SQLITE_CONFIG_MEMSTATUS, 0);
#endif





      }else if( strcmp(z,"nosync")==0 ){
        noSync = 1;
      }else if( strcmp(z,"notnull")==0 ){
        g.zNN = "NOT NULL";
#ifdef SQLITE_ENABLE_RBU
      }else if( strcmp(z,"rbu")==0 ){
        sqlite3ota_create_vfs("rbu", 0);
................................................................................
#endif

  /* Set database connection options */
  sqlite3_create_function(g.db, "random", 0, SQLITE_UTF8, 0, randomFunc, 0, 0);
#ifndef SQLITE_OMIT_DEPRECATED
  if( doTrace ) sqlite3_trace(g.db, traceCallback, 0);
#endif



  speedtest1_exec("PRAGMA threads=%d", nThread);
  if( zKey ){
    speedtest1_exec("PRAGMA key('%s')", zKey);
  }
  if( zEncoding ){
    speedtest1_exec("PRAGMA encoding=%s", zEncoding);
  }







>







 







>







 







>
>
>
>
>







 







>
>
>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
....
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
....
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
....
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
  "  --exclusive         Enable locking_mode=EXCLUSIVE\n"
  "  --explain           Like --sqlonly but with added EXPLAIN keywords\n"
  "  --heap SZ MIN       Memory allocator uses SZ bytes & min allocation MIN\n"
  "  --incrvacuum        Enable incremenatal vacuum mode\n"
  "  --journal M         Set the journal_mode to M\n"
  "  --key KEY           Set the encryption key to KEY\n"
  "  --lookaside N SZ    Configure lookaside for N slots of SZ bytes each\n"
  "  --mmap SZ           MMAP the first SZ bytes of the database file\n"
  "  --multithread       Set multithreaded mode\n"
  "  --nomemstat         Disable memory statistics\n"
  "  --nosync            Set PRAGMA synchronous=OFF\n"
  "  --notnull           Add NOT NULL constraints to table columns\n"
  "  --pagesize N        Set the page size to N\n"
  "  --pcache N SZ       Configure N pages of pagecache each of size SZ bytes\n"
  "  --primarykey        Use PRIMARY KEY instead of UNIQUE where appropriate\n"
................................................................................
  int noSync = 0;               /* True for --nosync */
  int pageSize = 0;             /* Desired page size.  0 means default */
  int nPCache = 0, szPCache = 0;/* --pcache configuration */
  int doPCache = 0;             /* True if --pcache is seen */
  int nScratch = 0, szScratch=0;/* --scratch configuration */
  int showStats = 0;            /* True for --stats */
  int nThread = 0;              /* --threads value */
  int mmapSize = 0;             /* How big of a memory map to use */
  const char *zTSet = "main";   /* Which --testset torun */
  int doTrace = 0;              /* True for --trace */
  const char *zEncoding = 0;    /* --utf16be or --utf16le */
  const char *zDbName = 0;      /* Name of the test database */

  void *pHeap = 0;              /* Allocated heap space */
  void *pLook = 0;              /* Allocated lookaside space */
................................................................................
        i += 2;
#if SQLITE_VERSION_NUMBER>=3006000
      }else if( strcmp(z,"multithread")==0 ){
        sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
      }else if( strcmp(z,"nomemstat")==0 ){
        sqlite3_config(SQLITE_CONFIG_MEMSTATUS, 0);
#endif
#if SQLITE_VERSION_NUMBER>=3007017
      }else if( strcmp(z, "mmap")==0 ){
        if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
        mmapSize = integerValue(argv[++i]);
 #endif
      }else if( strcmp(z,"nosync")==0 ){
        noSync = 1;
      }else if( strcmp(z,"notnull")==0 ){
        g.zNN = "NOT NULL";
#ifdef SQLITE_ENABLE_RBU
      }else if( strcmp(z,"rbu")==0 ){
        sqlite3ota_create_vfs("rbu", 0);
................................................................................
#endif

  /* Set database connection options */
  sqlite3_create_function(g.db, "random", 0, SQLITE_UTF8, 0, randomFunc, 0, 0);
#ifndef SQLITE_OMIT_DEPRECATED
  if( doTrace ) sqlite3_trace(g.db, traceCallback, 0);
#endif
  if( mmapSize>0 ){
    speedtest1_exec("PRAGMA mmap_size=%d", mmapSize);
  }
  speedtest1_exec("PRAGMA threads=%d", nThread);
  if( zKey ){
    speedtest1_exec("PRAGMA key('%s')", zKey);
  }
  if( zEncoding ){
    speedtest1_exec("PRAGMA encoding=%s", zEncoding);
  }

Changes to test/tempdb2.test.

70
71
72
73
74
75
76
77
}

do_execsql_test 1.4 {
  SELECT b=int2str(2) FROM t1
} {1 1 1}

finish_test








<
70
71
72
73
74
75
76

}

do_execsql_test 1.4 {
  SELECT b=int2str(2) FROM t1
} {1 1 1}

finish_test

Changes to test/temptrigger.test.

232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
do_test 5.1 {
  sqlite3 db2 test.db
  execsql { DROP TABLE t1 } db2
} {}

do_execsql_test 5.2 {
  SELECT * FROM sqlite_master;
  SELECT * FROM sqlite_temp_master;
} {
  trigger tr1 t1 0 
  {CREATE TRIGGER tr1 BEFORE INSERT ON t1 BEGIN SELECT 1,2,3; END}
}
db2 close

#-------------------------------------------------------------------------







|







232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
do_test 5.1 {
  sqlite3 db2 test.db
  execsql { DROP TABLE t1 } db2
} {}

do_execsql_test 5.2 {
  SELECT * FROM sqlite_master;
  SELECT * FROM temp.sqlite_master;
} {
  trigger tr1 t1 0 
  {CREATE TRIGGER tr1 BEFORE INSERT ON t1 BEGIN SELECT 1,2,3; END}
}
db2 close

#-------------------------------------------------------------------------

Changes to test/tkt3630.test.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
35
36
37
38
39
40
41
42
43
44
45
46
47
set testdir [file dirname $argv0]

source $testdir/tester.tcl

do_test tkt3630-1 {
  db eval {
    CREATE TEMP TABLE temp1(a,b,c);
    SELECT * FROM sqlite_temp_master WHERE sql GLOB '*TEMP*';
  }
} {}
do_test tkt3630-2 {
  db eval {
    CREATE TABLE main1(a,b,c);
    CREATE TEMP TABLE temp2 AS SELECT * FROM main1;
    SELECT * FROM sqlite_temp_master WHERE sql GLOB '*TEMP*';
................................................................................
} {}

ifcapable altertable {
  do_test tkt3630-3 {
    db eval {
      ALTER TABLE temp2 ADD COLUMN d;
      ALTER TABLE temp2 RENAME TO temp2rn;
      SELECT name FROM sqlite_temp_master WHERE name LIKE 'temp2%';
    }
  } {temp2rn}
}

finish_test







|







 







|





19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
35
36
37
38
39
40
41
42
43
44
45
46
47
set testdir [file dirname $argv0]

source $testdir/tester.tcl

do_test tkt3630-1 {
  db eval {
    CREATE TEMP TABLE temp1(a,b,c);
    SELECT * FROM temp.sqlite_master WHERE sql GLOB '*TEMP*';
  }
} {}
do_test tkt3630-2 {
  db eval {
    CREATE TABLE main1(a,b,c);
    CREATE TEMP TABLE temp2 AS SELECT * FROM main1;
    SELECT * FROM sqlite_temp_master WHERE sql GLOB '*TEMP*';
................................................................................
} {}

ifcapable altertable {
  do_test tkt3630-3 {
    db eval {
      ALTER TABLE temp2 ADD COLUMN d;
      ALTER TABLE temp2 RENAME TO temp2rn;
      SELECT name FROM temp.sqlite_master WHERE name LIKE 'temp2%';
    }
  } {temp2rn}
}

finish_test

Changes to test/tkt3810.test.

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  }
} {0 {}}

# Trigger still exists in the sqlite_temp_master table, but now it is
# an orphan.
#
do_test tkt3810-4 {
  execsql {SELECT name FROM sqlite_temp_master ORDER BY name}
} {r1}

# Because it is an orphan, it cannot be dropped.
#
do_test tkt3810-5 {
  catchsql {DROP TRIGGER r1}
} {1 {no such trigger: r1}}







|







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  }
} {0 {}}

# Trigger still exists in the sqlite_temp_master table, but now it is
# an orphan.
#
do_test tkt3810-4 {
  execsql {SELECT name FROM temp.sqlite_master ORDER BY name}
} {r1}

# Because it is an orphan, it cannot be dropped.
#
do_test tkt3810-5 {
  catchsql {DROP TRIGGER r1}
} {1 {no such trigger: r1}}

Changes to test/with3.test.

56
57
58
59
60
61
62
63
























































64
  CREATE TABLE t1(x);
  WITH
    x1(a) AS (values(100))
  INSERT INTO t1(x)
    SELECT * FROM (WITH x2(y) AS (SELECT * FROM x1) SELECT y+a FROM x1, x2);
  SELECT * FROM t1;
} {200}

























































finish_test








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

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
111
112
113
114
115
116
117
118
119
120
  CREATE TABLE t1(x);
  WITH
    x1(a) AS (values(100))
  INSERT INTO t1(x)
    SELECT * FROM (WITH x2(y) AS (SELECT * FROM x1) SELECT y+a FROM x1, x2);
  SELECT * FROM t1;
} {200}

#-------------------------------------------------------------------------
# Test that the planner notices LIMIT clauses on recursive WITH queries.
#

ifcapable analyze {
  do_execsql_test 3.1.1 {
    CREATE TABLE y1(a, b);
    CREATE INDEX y1a ON y1(a);

    WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1000)
      INSERT INTO y1 SELECT i%10, i FROM cnt;
    ANALYZE;

  }

  do_eqp_test 3.1.2 {
    WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1)
    SELECT * FROM cnt, y1 WHERE i=a
  } {
    3 0 0 {SCAN TABLE cnt} 
    1 0 0 {COMPOUND SUBQUERIES 0 AND 0 (UNION ALL)}
    0 0 0 {SCAN SUBQUERY 1} 
    0 1 1 {SEARCH TABLE y1 USING INDEX y1a (a=?)}
  }

  do_eqp_test 3.1.3 {
    WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1000000)
    SELECT * FROM cnt, y1 WHERE i=a
  } {
    3 0 0 {SCAN TABLE cnt} 
    1 0 0 {COMPOUND SUBQUERIES 0 AND 0 (UNION ALL)}
    0 0 1 {SCAN TABLE y1} 
    0 1 0 {SEARCH SUBQUERY 1 USING AUTOMATIC COVERING INDEX (i=?)}
  }
}

do_execsql_test 3.2.1 {
  CREATE TABLE w1(pk INTEGER PRIMARY KEY, x INTEGER);
  CREATE TABLE w2(pk INTEGER PRIMARY KEY);
}

do_eqp_test 3.2.2 {
  WITH RECURSIVE c(w,id) AS (SELECT 0, (SELECT pk FROM w2 LIMIT 1)
     UNION ALL SELECT c.w + 1, x FROM w1, c LIMIT 1)
     SELECT * FROM c, w2, w1
     WHERE c.id=w2.pk AND c.id=w1.pk;
} {
  2 0 0 {EXECUTE SCALAR SUBQUERY 3} 
  3 0 0 {SCAN TABLE w2} 
  4 0 0 {SCAN TABLE w1}
  4 1 1 {SCAN TABLE c} 
  1 0 0 {COMPOUND SUBQUERIES 0 AND 0 (UNION ALL)} 0 0 0 {SCAN SUBQUERY 1}
  0 1 1 {SEARCH TABLE w2 USING INTEGER PRIMARY KEY (rowid=?)} 
  0 2 2 {SEARCH TABLE w1 USING INTEGER PRIMARY KEY (rowid=?)}
}

finish_test

Changes to test/without_rowid3.test.

1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
....
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
    catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 }
  } {1 {Cannot add a REFERENCES column with non-NULL default value}}
  do_test without_rowid3-14.1tmp.6 {
    execsql { 
      PRAGMA foreign_keys = off;
      ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
      PRAGMA foreign_keys = on;
      SELECT sql FROM sqlite_temp_master WHERE name='t2';
    }
  } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}

  do_test without_rowid3-14.2tmp.1.1 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
  } {{CREATE TABLE t1(a REFERENCES "t3")}}
  do_test without_rowid3-14.2tmp.1.2 {
................................................................................
    {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid}       \
    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)
            WITHOUT rowid}    \
    {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)}  \
  ]
  do_test without_rowid3-14.2tmp.2.2 {
    execsql { ALTER TABLE t1 RENAME TO t4 }
    execsql { SELECT sql FROM sqlite_temp_master WHERE type = 'table'}
  } [list \
    {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4") WITHOUT rowid}      \
    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)
            WITHOUT rowid}     \
    {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \
  ]
  do_test without_rowid3-14.2tmp.2.3 {







|







 







|







1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
....
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
    catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 }
  } {1 {Cannot add a REFERENCES column with non-NULL default value}}
  do_test without_rowid3-14.1tmp.6 {
    execsql { 
      PRAGMA foreign_keys = off;
      ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
      PRAGMA foreign_keys = on;
      SELECT sql FROM temp.sqlite_master WHERE name='t2';
    }
  } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}

  do_test without_rowid3-14.2tmp.1.1 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
  } {{CREATE TABLE t1(a REFERENCES "t3")}}
  do_test without_rowid3-14.2tmp.1.2 {
................................................................................
    {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid}       \
    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)
            WITHOUT rowid}    \
    {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)}  \
  ]
  do_test without_rowid3-14.2tmp.2.2 {
    execsql { ALTER TABLE t1 RENAME TO t4 }
    execsql { SELECT sql FROM temp.sqlite_master WHERE type = 'table'}
  } [list \
    {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4") WITHOUT rowid}      \
    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)
            WITHOUT rowid}     \
    {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \
  ]
  do_test without_rowid3-14.2tmp.2.3 {

Changes to tool/speed-check.sh.

86
87
88
89
90
91
92




93
94
95
96
97
98
99
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --heap $1 64"
        ;;
    --repeat)
        CC_OPTS="$CC_OPTS -DSQLITE_ENABLE_RCACHE"
        shift;
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --repeat $1"
        ;;




    *)
        CC_OPTS="$CC_OPTS $1"
        ;;
  esac
  shift
done
SPEEDTEST_OPTS="$SPEEDTEST_OPTS --size $SIZE"







>
>
>
>







86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --heap $1 64"
        ;;
    --repeat)
        CC_OPTS="$CC_OPTS -DSQLITE_ENABLE_RCACHE"
        shift;
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --repeat $1"
        ;;
    --mmap)
        shift;
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --mmap $1"
        ;;
    *)
        CC_OPTS="$CC_OPTS $1"
        ;;
  esac
  shift
done
SPEEDTEST_OPTS="$SPEEDTEST_OPTS --size $SIZE"