/ Check-in [be661acf]
Login

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

Overview
Comment:Insert #ifdefs that can optionally remove features at compiletime resulting in a database engine with a smaller footprint. (CVS 2034)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:be661acfa849bb0d5692797dd221f5a8a457f8ad
User & Date: drh 2004-10-31 02:22:48
Context
2004-10-31
16:25
Add code to create/update the btree 'pointer-map' for auto-vacuum mode. (CVS 2035) check-in: bebd967f user: danielk1977 tags: trunk
02:22
Insert #ifdefs that can optionally remove features at compiletime resulting in a database engine with a smaller footprint. (CVS 2034) check-in: be661acf user: drh tags: trunk
2004-10-30
20:23
Begin adding the ability to remove unused features at compile-time and still have all the tests pass. (CVS 2033) check-in: 2aa506cc user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to mkopcodec.awk.

7
8
9
10
11
12
13




14
15
16
17
18
19
20
21

22
# Opcodes.c contains strings which are the symbolic names for the various
# opcodes used by the VDBE.  These strings are used when disassembling a
# VDBE program during tracing or as a result of the EXPLAIN keyword.
#
BEGIN {
  print "/* Automatically generated.  Do not edit */"
  print "/* See the mkopcodec.h script for details. */"




  print "const char *const sqlite3OpcodeNames[] = { \"?\","
}
/^#define OP_/ {
  sub("OP_","",$2)
  print "  \"" $2 "\","
}
END {
  print "};"

}







>
>
>
>








>

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# Opcodes.c contains strings which are the symbolic names for the various
# opcodes used by the VDBE.  These strings are used when disassembling a
# VDBE program during tracing or as a result of the EXPLAIN keyword.
#
BEGIN {
  print "/* Automatically generated.  Do not edit */"
  print "/* See the mkopcodec.h script for details. */"
  printf "#if !defined(SQLITE_OMIT_EXPLAIN)"
  printf    " || !defined(NDEBUG)"
  printf    " || defined(VDBE_PROFILE)"
  print     " || defined(SQLITE_DEBUG)"
  print "const char *const sqlite3OpcodeNames[] = { \"?\","
}
/^#define OP_/ {
  sub("OP_","",$2)
  print "  \"" $2 "\","
}
END {
  print "};"
  print "#endif"
}

Changes to src/btree.c.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
....
4063
4064
4065
4066
4067
4068
4069

4070
4071
4072
4073
4074
4075
4076
....
4088
4089
4090
4091
4092
4093
4094

4095

4096
4097
4098
4099
4100
4101
4102
....
4109
4110
4111
4112
4113
4114
4115

4116

4117
4118
4119
4120
4121
4122
4123
....
4154
4155
4156
4157
4158
4159
4160

4161

4162
4163
4164
4165
4166
4167
4168
....
4292
4293
4294
4295
4296
4297
4298

4299

4300
4301
4302
4303
4304
4305
4306
....
4362
4363
4364
4365
4366
4367
4368

4369
4370
4371
4372
4373
4374
4375
....
4389
4390
4391
4392
4393
4394
4395

4396
4397
4398
4399
4400
4401
4402
....
4430
4431
4432
4433
4434
4435
4436

4437
4438
4439
4440
4441
4442
4443
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.193 2004/10/22 16:22:58 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
**
**     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
**     "Sorting And Searching", pages 473-480. Addison-Wesley
**     Publishing Company, Reading, Massachusetts.
................................................................................
  Btree *pBt;    /* The tree being checked out */
  Pager *pPager; /* The associated pager.  Also accessible by pBt->pPager */
  int nPage;     /* Number of pages in the database */
  int *anRef;    /* Number of times each page is referenced */
  char *zErrMsg; /* An error message.  NULL of no errors seen. */
};


/*
** Append a message to the error message string.
*/
static void checkAppendMsg(
  IntegrityCk *pCheck,
  char *zMsg1,
  const char *zFormat,
................................................................................
    sqlite3SetString(&pCheck->zErrMsg, zOld, "\n", zMsg1, zMsg2, (char*)0);
    sqliteFree(zOld);
  }else{
    sqlite3SetString(&pCheck->zErrMsg, zMsg1, zMsg2, (char*)0);
  }
  sqliteFree(zMsg2);
}



/*
** Add 1 to the reference count for page iPage.  If this is the second
** reference to the page, add an error message to pCheck->zErrMsg.
** Return 1 if there are 2 ore more references to the page and 0 if
** if this is the first reference to the page.
**
** Also check that the page number is in bounds.
................................................................................
  }
  if( pCheck->anRef[iPage]==1 ){
    checkAppendMsg(pCheck, zContext, "2nd reference to page %d", iPage);
    return 1;
  }
  return  (pCheck->anRef[iPage]++)>1;
}



/*
** Check the integrity of the freelist or of an overflow page list.
** Verify that the number of pages on the list is N.
*/
static void checkList(
  IntegrityCk *pCheck,  /* Integrity checking context */
  int isFreeList,       /* True for a freelist.  False for overflow page list */
................................................................................
        N -= n;
      }
    }
    iPage = get4byte(pOvfl);
    sqlite3pager_unref(pOvfl);
  }
}



/*
** Do various sanity checks on a single page of a tree.  Return
** the tree depth.  Root pages return 0.  Parents of root pages
** return 1, and so forth.
** 
** These checks are done:
**
................................................................................
    }
  }
  sqliteFree(hit);

  releasePage(pPage);
  return depth+1;
}



/*
** This routine does a complete check of the given BTree file.  aRoot[] is
** an array of pages numbers were each page number is the root page of
** a table.  nRoot is the number of entries in aRoot.
**
** If everything checks out, this routine returns NULL.  If something is
** amiss, an error message is written into memory obtained from malloc()
................................................................................
  }

  /* Clean  up and report errors.
  */
  sqliteFree(sCheck.anRef);
  return sCheck.zErrMsg;
}


/*
** Return the full pathname of the underlying database file.
*/
const char *sqlite3BtreeGetFilename(Btree *pBt){
  assert( pBt->pPager!=0 );
  return sqlite3pager_filename(pBt->pPager);
................................................................................
** has been created or not.
*/
const char *sqlite3BtreeGetJournalname(Btree *pBt){
  assert( pBt->pPager!=0 );
  return sqlite3pager_journalname(pBt->pPager);
}


/*
** Copy the complete content of pBtFrom into pBtTo.  A transaction
** must be active for both files.
**
** The size of file pBtFrom may be reduced by this operation.
** If anything goes wrong, the transaction on pBtFrom is rolled back.
*/
................................................................................
    rc = sqlite3pager_truncate(pBtTo->pPager, nPage);
  }
  if( rc ){
    sqlite3BtreeRollback(pBtTo);
  }
  return rc;  
}


/*
** Return non-zero if a transaction is active.
*/
int sqlite3BtreeIsInTrans(Btree *pBt){
  return (pBt && (pBt->inTrans==TRANS_WRITE));
}







|







 







>







 







>

>







 







>

>







 







>

>







 







>

>







 







>







 







>







 







>







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
....
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
....
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
....
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
....
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
....
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
....
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
....
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
....
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.194 2004/10/31 02:22:49 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
**
**     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
**     "Sorting And Searching", pages 473-480. Addison-Wesley
**     Publishing Company, Reading, Massachusetts.
................................................................................
  Btree *pBt;    /* The tree being checked out */
  Pager *pPager; /* The associated pager.  Also accessible by pBt->pPager */
  int nPage;     /* Number of pages in the database */
  int *anRef;    /* Number of times each page is referenced */
  char *zErrMsg; /* An error message.  NULL of no errors seen. */
};

#ifndef SQLITE_OMIT_INTEGRITY_CHECK
/*
** Append a message to the error message string.
*/
static void checkAppendMsg(
  IntegrityCk *pCheck,
  char *zMsg1,
  const char *zFormat,
................................................................................
    sqlite3SetString(&pCheck->zErrMsg, zOld, "\n", zMsg1, zMsg2, (char*)0);
    sqliteFree(zOld);
  }else{
    sqlite3SetString(&pCheck->zErrMsg, zMsg1, zMsg2, (char*)0);
  }
  sqliteFree(zMsg2);
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

#ifndef SQLITE_OMIT_INTEGRITY_CHECK
/*
** Add 1 to the reference count for page iPage.  If this is the second
** reference to the page, add an error message to pCheck->zErrMsg.
** Return 1 if there are 2 ore more references to the page and 0 if
** if this is the first reference to the page.
**
** Also check that the page number is in bounds.
................................................................................
  }
  if( pCheck->anRef[iPage]==1 ){
    checkAppendMsg(pCheck, zContext, "2nd reference to page %d", iPage);
    return 1;
  }
  return  (pCheck->anRef[iPage]++)>1;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

#ifndef SQLITE_OMIT_INTEGRITY_CHECK
/*
** Check the integrity of the freelist or of an overflow page list.
** Verify that the number of pages on the list is N.
*/
static void checkList(
  IntegrityCk *pCheck,  /* Integrity checking context */
  int isFreeList,       /* True for a freelist.  False for overflow page list */
................................................................................
        N -= n;
      }
    }
    iPage = get4byte(pOvfl);
    sqlite3pager_unref(pOvfl);
  }
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

#ifndef SQLITE_OMIT_INTEGRITY_CHECK
/*
** Do various sanity checks on a single page of a tree.  Return
** the tree depth.  Root pages return 0.  Parents of root pages
** return 1, and so forth.
** 
** These checks are done:
**
................................................................................
    }
  }
  sqliteFree(hit);

  releasePage(pPage);
  return depth+1;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

#ifndef SQLITE_OMIT_INTEGRITY_CHECK
/*
** This routine does a complete check of the given BTree file.  aRoot[] is
** an array of pages numbers were each page number is the root page of
** a table.  nRoot is the number of entries in aRoot.
**
** If everything checks out, this routine returns NULL.  If something is
** amiss, an error message is written into memory obtained from malloc()
................................................................................
  }

  /* Clean  up and report errors.
  */
  sqliteFree(sCheck.anRef);
  return sCheck.zErrMsg;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

/*
** Return the full pathname of the underlying database file.
*/
const char *sqlite3BtreeGetFilename(Btree *pBt){
  assert( pBt->pPager!=0 );
  return sqlite3pager_filename(pBt->pPager);
................................................................................
** has been created or not.
*/
const char *sqlite3BtreeGetJournalname(Btree *pBt){
  assert( pBt->pPager!=0 );
  return sqlite3pager_journalname(pBt->pPager);
}

#ifndef SQLITE_OMIT_VACUUM
/*
** Copy the complete content of pBtFrom into pBtTo.  A transaction
** must be active for both files.
**
** The size of file pBtFrom may be reduced by this operation.
** If anything goes wrong, the transaction on pBtFrom is rolled back.
*/
................................................................................
    rc = sqlite3pager_truncate(pBtTo->pPager, nPage);
  }
  if( rc ){
    sqlite3BtreeRollback(pBtTo);
  }
  return rc;  
}
#endif /* SQLITE_OMIT_VACUUM */

/*
** Return non-zero if a transaction is active.
*/
int sqlite3BtreeIsInTrans(Btree *pBt){
  return (pBt && (pBt->inTrans==TRANS_WRITE));
}

Changes to src/build.c.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
....
1396
1397
1398
1399
1400
1401
1402

1403
1404
1405
1406
1407
1408
1409
....
1457
1458
1459
1460
1461
1462
1463

1464

1465
1466
1467
1468
1469
1470
1471
....
1526
1527
1528
1529
1530
1531
1532

1533

1534
1535
1536
1537
1538
1539
1540
....
1541
1542
1543
1544
1545
1546
1547



1548
1549
1550
1551
1552
1553
1554
....
1689
1690
1691
1692
1693
1694
1695


1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
....
1775
1776
1777
1778
1779
1780
1781

1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793

1794
1795
1796
1797

1798
1799
1800
1801
1802
1803
1804
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.257 2004/10/06 15:41:16 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Check to see if the schema for the database needs
................................................................................
    }
    pParse->pNewTable = 0;
    db->nTable++;
    db->flags |= SQLITE_InternChanges;
  }
}


/*
** The parser calls this routine in order to create a new VIEW
*/
void sqlite3CreateView(
  Parse *pParse,     /* The parsing context */
  Token *pBegin,     /* The CREATE token that begins the statement */
  Token *pName1,     /* The token that holds the name of the view */
................................................................................
  sEnd.z = &z[n-1];
  sEnd.n = 1;

  /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */
  sqlite3EndTable(pParse, &sEnd, 0);
  return;
}



/*
** The Table structure pTable is really a VIEW.  Fill in the names of
** the columns of the view in the pTable structure.  Return the number
** of errors.  If an error is seen leave an error message in pParse->zErrMsg.
*/
int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
  ExprList *pEList;
................................................................................
    nErr++;
  }
  sqlite3SelectUnbind(pSel);
  sqlite3ExprListDelete(pSel->pEList);
  pSel->pEList = pEList;
  return nErr;  
}



/*
** Clear the column names from every VIEW in database idx.
*/
static void sqliteViewResetAll(sqlite3 *db, int idx){
  HashElem *i;
  if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
  for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){
................................................................................
    Table *pTab = sqliteHashData(i);
    if( pTab->pSelect ){
      sqliteResetColumnNames(pTab);
    }
  }
  DbClearProperty(db, idx, DB_UnresetViews);
}




/*
** This routine is called to do the work of a DROP TABLE statement.
** pName is the name of the table to be dropped.
*/
void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
  Table *pTab;
................................................................................
void sqlite3CreateForeignKey(
  Parse *pParse,       /* Parsing context */
  ExprList *pFromCol,  /* Columns in this table that point to other table */
  Token *pTo,          /* Name of the other table */
  ExprList *pToCol,    /* Columns in the other table */
  int flags            /* Conflict resolution algorithms. */
){


  Table *p = pParse->pNewTable;
  int nByte;
  int i;
  int nCol;
  char *z;
  FKey *pFKey = 0;

  assert( pTo!=0 );
  if( p==0 || pParse->nErr ) goto fk_end;
  if( pFromCol==0 ){
    int iCol = p->nCol-1;
    if( iCol<0 ) goto fk_end;
    if( pToCol && pToCol->nExpr!=1 ){
................................................................................
  /* Link the foreign key to the table as the last step.
  */
  p->pFKey = pFKey;
  pFKey = 0;

fk_end:
  sqliteFree(pFKey);

  sqlite3ExprListDelete(pFromCol);
  sqlite3ExprListDelete(pToCol);
}

/*
** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED
** clause is seen as part of a foreign key definition.  The isDeferred
** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE.
** The behavior of the most recently created foreign key is adjusted
** accordingly.
*/
void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){

  Table *pTab;
  FKey *pFKey;
  if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;
  pFKey->isDeferred = isDeferred;

}

/*
** Create a new index for an SQL table.  pIndex is the name of the index 
** and pTable is the name of the table that is to be indexed.  Both will 
** be NULL for a primary key or an index that is created to satisfy a
** UNIQUE constraint.  If pTable and pIndex are NULL, use pParse->pNewTable







|







 







>







 







>

>







 







>

>







 







>
>
>







 







>
>





<







 







>












>




>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
....
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
....
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
....
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
....
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
....
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710

1711
1712
1713
1714
1715
1716
1717
....
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.258 2004/10/31 02:22:49 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Check to see if the schema for the database needs
................................................................................
    }
    pParse->pNewTable = 0;
    db->nTable++;
    db->flags |= SQLITE_InternChanges;
  }
}

#ifndef SQLITE_OMIT_VIEW
/*
** The parser calls this routine in order to create a new VIEW
*/
void sqlite3CreateView(
  Parse *pParse,     /* The parsing context */
  Token *pBegin,     /* The CREATE token that begins the statement */
  Token *pName1,     /* The token that holds the name of the view */
................................................................................
  sEnd.z = &z[n-1];
  sEnd.n = 1;

  /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */
  sqlite3EndTable(pParse, &sEnd, 0);
  return;
}
#endif /* SQLITE_OMIT_VIEW */

#ifndef SQLITE_OMIT_VIEW
/*
** The Table structure pTable is really a VIEW.  Fill in the names of
** the columns of the view in the pTable structure.  Return the number
** of errors.  If an error is seen leave an error message in pParse->zErrMsg.
*/
int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
  ExprList *pEList;
................................................................................
    nErr++;
  }
  sqlite3SelectUnbind(pSel);
  sqlite3ExprListDelete(pSel->pEList);
  pSel->pEList = pEList;
  return nErr;  
}
#endif /* SQLITE_OMIT_VIEW */

#ifndef SQLITE_OMIT_VIEW
/*
** Clear the column names from every VIEW in database idx.
*/
static void sqliteViewResetAll(sqlite3 *db, int idx){
  HashElem *i;
  if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
  for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){
................................................................................
    Table *pTab = sqliteHashData(i);
    if( pTab->pSelect ){
      sqliteResetColumnNames(pTab);
    }
  }
  DbClearProperty(db, idx, DB_UnresetViews);
}
#else
# define sqliteViewResetAll(A,B)
#endif /* SQLITE_OMIT_VIEW */

/*
** This routine is called to do the work of a DROP TABLE statement.
** pName is the name of the table to be dropped.
*/
void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
  Table *pTab;
................................................................................
void sqlite3CreateForeignKey(
  Parse *pParse,       /* Parsing context */
  ExprList *pFromCol,  /* Columns in this table that point to other table */
  Token *pTo,          /* Name of the other table */
  ExprList *pToCol,    /* Columns in the other table */
  int flags            /* Conflict resolution algorithms. */
){
  FKey *pFKey = 0;
#ifndef SQLITE_OMIT_FOREIGN_KEY
  Table *p = pParse->pNewTable;
  int nByte;
  int i;
  int nCol;
  char *z;


  assert( pTo!=0 );
  if( p==0 || pParse->nErr ) goto fk_end;
  if( pFromCol==0 ){
    int iCol = p->nCol-1;
    if( iCol<0 ) goto fk_end;
    if( pToCol && pToCol->nExpr!=1 ){
................................................................................
  /* Link the foreign key to the table as the last step.
  */
  p->pFKey = pFKey;
  pFKey = 0;

fk_end:
  sqliteFree(pFKey);
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
  sqlite3ExprListDelete(pFromCol);
  sqlite3ExprListDelete(pToCol);
}

/*
** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED
** clause is seen as part of a foreign key definition.  The isDeferred
** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE.
** The behavior of the most recently created foreign key is adjusted
** accordingly.
*/
void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
#ifndef SQLITE_OMIT_FOREIGN_KEY
  Table *pTab;
  FKey *pFKey;
  if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;
  pFKey->isDeferred = isDeferred;
#endif
}

/*
** Create a new index for an SQL table.  pIndex is the name of the index 
** and pTable is the name of the table that is to be indexed.  Both will 
** be NULL for a primary key or an index that is created to satisfy a
** UNIQUE constraint.  If pTable and pIndex are NULL, use pParse->pNewTable

Changes to src/delete.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
100
101
102
103
104
105
106





107
108
109
110
111
112











113
114
115
116
117
118
119
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.83 2004/10/22 20:29:22 drh Exp $
*/
#include "sqliteInt.h"

/*
** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.
................................................................................
  /* Locate the table which we want to delete.  This table has to be
  ** put in an SrcList structure because some of the subroutines we
  ** will be calling are designed to work with multiple tables and expect
  ** an SrcList* parameter instead of just a Table* parameter.
  */
  pTab = sqlite3SrcListLookup(pParse, pTabList);
  if( pTab==0 )  goto delete_from_cleanup;





  before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, 
                         TK_DELETE, TK_BEFORE, TK_ROW, 0);
  after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, 
                         TK_DELETE, TK_AFTER, TK_ROW, 0);
  row_triggers_exist = before_triggers || after_triggers;
  isView = pTab->pSelect!=0;











  if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){
    goto delete_from_cleanup;
  }
  assert( pTab->iDb<db->nDb );
  zDb = db->aDb[pTab->iDb].zName;
  if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
    goto delete_from_cleanup;







|







 







>
>
>
>
>






>
>
>
>
>
>
>
>
>
>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.84 2004/10/31 02:22:49 drh Exp $
*/
#include "sqliteInt.h"

/*
** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.
................................................................................
  /* Locate the table which we want to delete.  This table has to be
  ** put in an SrcList structure because some of the subroutines we
  ** will be calling are designed to work with multiple tables and expect
  ** an SrcList* parameter instead of just a Table* parameter.
  */
  pTab = sqlite3SrcListLookup(pParse, pTabList);
  if( pTab==0 )  goto delete_from_cleanup;

  /* Figure out if we have any triggers and if the table being
  ** deleted from is a view
  */
#ifndef SQLITE_OMIT_TRIGGER
  before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, 
                         TK_DELETE, TK_BEFORE, TK_ROW, 0);
  after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, 
                         TK_DELETE, TK_AFTER, TK_ROW, 0);
  row_triggers_exist = before_triggers || after_triggers;
  isView = pTab->pSelect!=0;
#else
# define before_triggers 0
# define after_triggers 0
# define row_triggers_exist 0
# define isView 0
#endif
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif

  if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){
    goto delete_from_cleanup;
  }
  assert( pTab->iDb<db->nDb );
  zDb = db->aDb[pTab->iDb].zName;
  if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
    goto delete_from_cleanup;

Changes to src/expr.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
696
697
698
699
700
701
702

703
704
705
706
707
708
709
...
729
730
731
732
733
734
735

736
737
738
739
740
741
742
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.166 2004/10/04 13:19:24 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**
................................................................................
        pExpr->affinity = pTab->aCol[j].affinity;
        pExpr->pColl = pTab->aCol[j].pColl;
        break;
      }
    }
  }


  /* If we have not already resolved the name, then maybe 
  ** it is a new.* or old.* trigger argument reference
  */
  if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
    TriggerStack *pTriggerStack = pParse->trigStack;
    Table *pTab = 0;
    if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){
................................................................................
          pExpr->affinity = pTab->aCol[j].affinity;
          pExpr->pColl = pTab->aCol[j].pColl;
          break;
        }
      }
    }
  }


  /*
  ** Perhaps the name is a reference to the ROWID
  */
  if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
    cnt = 1;
    pExpr->iColumn = -1;







|







 







>







 







>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
...
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.167 2004/10/31 02:22:49 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**
................................................................................
        pExpr->affinity = pTab->aCol[j].affinity;
        pExpr->pColl = pTab->aCol[j].pColl;
        break;
      }
    }
  }

#ifndef SQLITE_OMIT_TRIGGER
  /* If we have not already resolved the name, then maybe 
  ** it is a new.* or old.* trigger argument reference
  */
  if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
    TriggerStack *pTriggerStack = pParse->trigStack;
    Table *pTab = 0;
    if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){
................................................................................
          pExpr->affinity = pTab->aCol[j].affinity;
          pExpr->pColl = pTab->aCol[j].pColl;
          break;
        }
      }
    }
  }
#endif /* !defined(SQLITE_OMIT_TRIGGER) */

  /*
  ** Perhaps the name is a reference to the ROWID
  */
  if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
    cnt = 1;
    pExpr->iColumn = -1;

Changes to src/insert.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
208
209
210
211
212
213
214





















215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.119 2004/10/05 02:41:42 drh Exp $
*/
#include "sqliteInt.h"

/*
** Set P3 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
................................................................................
    goto insert_cleanup;
  }
  assert( pTab->iDb<db->nDb );
  zDb = db->aDb[pTab->iDb].zName;
  if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){
    goto insert_cleanup;
  }






















  /* Ensure that:
  *  (a) the table is not read-only, 
  *  (b) that if it is a view then ON INSERT triggers exist
  */
  before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, TK_INSERT, 
                                       TK_BEFORE, TK_ROW, 0);
  after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, TK_INSERT,
                                       TK_AFTER, TK_ROW, 0);
  row_triggers_exist = before_triggers || after_triggers;
  isView = pTab->pSelect!=0;
  if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){
    goto insert_cleanup;
  }
  if( pTab==0 ) goto insert_cleanup;

  /* If pTab is really a view, make sure it has been initialized.
  */







|







 







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





<
<
<
<
<
<







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240






241
242
243
244
245
246
247
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.120 2004/10/31 02:22:49 drh Exp $
*/
#include "sqliteInt.h"

/*
** Set P3 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
................................................................................
    goto insert_cleanup;
  }
  assert( pTab->iDb<db->nDb );
  zDb = db->aDb[pTab->iDb].zName;
  if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){
    goto insert_cleanup;
  }

  /* Figure out if we have any triggers and if the table being
  ** inserted into is a view
  */
#ifndef SQLITE_OMIT_TRIGGER
  before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, 
                         TK_INSERT, TK_BEFORE, TK_ROW, 0);
  after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, 
                         TK_INSERT, TK_AFTER, TK_ROW, 0);
  row_triggers_exist = before_triggers || after_triggers;
  isView = pTab->pSelect!=0;
#else
# define before_triggers 0
# define after_triggers 0
# define row_triggers_exist 0
# define isView 0
#endif
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif

  /* Ensure that:
  *  (a) the table is not read-only, 
  *  (b) that if it is a view then ON INSERT triggers exist
  */






  if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){
    goto insert_cleanup;
  }
  if( pTab==0 ) goto insert_cleanup;

  /* If pTab is really a view, make sure it has been initialized.
  */

Changes to src/pager.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
304
305
306
307
308
309
310















311
312
313
314
315
316
317
...
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
....
1450
1451
1452
1453
1454
1455
1456

1457
1458
1459
1460
1461


1462
1463
1464
1465
1466
1467
1468
....
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
....
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
....
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
....
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
....
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
....
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
....
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
....
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
....
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
....
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
....
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
....
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
....
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
....
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
....
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
....
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
....
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
....
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
....
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
....
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
....
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.168 2004/10/22 16:22:59 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include "pager.h"
#include <assert.h>
#include <string.h>

................................................................................
/*
** The journal header size for this pager. In the future, this could be
** set to some value read from the disk controller. The important
** characteristic is that it is the same size as a disk sector.
*/
#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize)
















#define PAGER_SECTOR_SIZE 512

/*
** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is
** reserved for working around a windows/posix incompatibility). It is
** used in the journal to signify that the remainder of the journal file 
** is devoted to storing a master journal name - there are no more pages to
................................................................................
** TODO: Consider keeping the journal file open for temporary databases.
** This might give a performance improvement on windows where opening
** a file is an expensive operation.
*/
static int pager_unwritelock(Pager *pPager){
  PgHdr *pPg;
  int rc;
  assert( !pPager->memDb );
  if( pPager->state<PAGER_RESERVED ){
    return SQLITE_OK;
  }
  sqlite3pager_stmt_commit(pPager);
  if( pPager->stmtOpen ){
    sqlite3OsClose(&pPager->stfd);
    pPager->stmtOpen = 0;
................................................................................

  *ppPager = 0;
  memset(&fd, 0, sizeof(fd));
  if( sqlite3_malloc_failed ){
    return SQLITE_NOMEM;
  }
  if( zFilename && zFilename[0] ){

    if( strcmp(zFilename,":memory:")==0 ){
      memDb = 1;
      zFullPathname = sqliteStrDup("");
      rc = SQLITE_OK;
    }else{


      zFullPathname = sqlite3OsFullPathname(zFilename);
      if( zFullPathname ){
        rc = sqlite3OsOpenReadWrite(zFullPathname, &fd, &readOnly);
      }
    }
  }else{
    rc = sqlite3pager_opentemp(zTemp, &fd);
................................................................................

/*
** Read the first N bytes from the beginning of the file into memory
** that pDest points to.  No error checking is done.
*/
void sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){
  memset(pDest, 0, N);
  if( pPager->memDb==0 ){
    sqlite3OsSeek(&pPager->fd, 0);
    sqlite3OsRead(&pPager->fd, pDest, N);
  }
}

/*
** Return the total number of pages in the disk file associated with
................................................................................
    return pPager->dbSize;
  }
  if( sqlite3OsFileSize(&pPager->fd, &n)!=SQLITE_OK ){
    pPager->errMask |= PAGER_ERR_DISK;
    return 0;
  }
  n /= pPager->pageSize;
  if( !pPager->memDb && n==PENDING_BYTE/pPager->pageSize ){
    n++;
  }
  if( pPager->state!=PAGER_UNLOCK ){
    pPager->dbSize = n;
  }
  return n;
}
................................................................................
  if( pPager->errMask!=0 ){
    rc = pager_errcode(pPager);
    return rc;
  }
  if( nPage>=(unsigned)pPager->dbSize ){
    return SQLITE_OK;
  }
  if( pPager->memDb ){
    pPager->dbSize = nPage;
    memoryTruncate(pPager);
    return SQLITE_OK;
  }
  rc = syncJournal(pPager);
  if( rc!=SQLITE_OK ){
    return rc;
................................................................................
int sqlite3pager_close(Pager *pPager){
  PgHdr *pPg, *pNext;
  switch( pPager->state ){
    case PAGER_RESERVED:
    case PAGER_SYNCED: 
    case PAGER_EXCLUSIVE: {
      sqlite3pager_rollback(pPager);
      if( !pPager->memDb ){
        sqlite3OsUnlock(&pPager->fd, NO_LOCK);
      }
      assert( pPager->journalOpen==0 );
      break;
    }
    case PAGER_SHARED: {
      if( !pPager->memDb ){
        sqlite3OsUnlock(&pPager->fd, NO_LOCK);
      }
      break;
    }
    default: {
      /* Do nothing */
      break;
    }
  }
  for(pPg=pPager->pAll; pPg; pPg=pNext){
#ifndef NDEBUG
    if( pPager->memDb ){
      PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
      assert( !pPg->alwaysRollback );
      assert( !pHist->pOrig );
      assert( !pHist->pStmt );
    }
#endif
    pNext = pPg->pNextAll;
................................................................................
  if( pPager->errMask & ~(PAGER_ERR_FULL) ){
    return pager_errcode(pPager);
  }

  /* If this is the first page accessed, then get a SHARED lock
  ** on the database file.
  */
  if( pPager->nRef==0 && !pPager->memDb ){
    rc = pager_wait_on_lock(pPager, SHARED_LOCK);
    if( rc!=SQLITE_OK ){
      return rc;
    }

    /* If a journal file exists, and there is no RESERVED lock on the
    ** database file, then it either needs to be played back or deleted.
................................................................................
         return rc;
       }
    }
    pPg = 0;
  }else{
    /* Search for page in cache */
    pPg = pager_lookup(pPager, pgno);
    if( pPager->memDb && pPager->state==PAGER_UNLOCK ){
      pPager->state = PAGER_SHARED;
    }
  }
  if( pPg==0 ){
    /* The requested page is not in the page cache. */
    int h;
    pPager->nMiss++;
    if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 || pPager->memDb ){
      /* Create a new page */
      pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->psAligned
                              + sizeof(u32) + pPager->nExtra
                              + pPager->memDb*sizeof(PgHistory) );
      if( pPg==0 ){
        if( !pPager->memDb ){
          pager_unwritelock(pPager);
        }
        pPager->errMask |= PAGER_ERR_MEM;
        return SQLITE_NOMEM;
      }
      memset(pPg, 0, sizeof(*pPg));
      if( pPager->memDb ){
        memset(PGHDR_TO_HIST(pPg, pPager), 0, sizeof(PgHistory));
      }
      pPg->pPager = pPager;
      pPg->pNextAll = pPager->pAll;
      pPager->pAll = pPg;
      pPager->nPage++;
    }else{
................................................................................
      rc = pager_errcode(pPager);
      return rc;
    }
    if( pPager->dbSize<(int)pgno ){
      memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
    }else{
      int rc;
      assert( pPager->memDb==0 );
      sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize);
      rc = sqlite3OsRead(&pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize);
      TRACE3("FETCH %d page %d\n", pPager->fd.h, pPg->pgno);
      CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
      if( rc!=SQLITE_OK ){
        i64 fileSize;
        if( sqlite3OsFileSize(&pPager->fd,&fileSize)!=SQLITE_OK
................................................................................
    }
  
    /* When all pages reach the freelist, drop the read lock from
    ** the database file.
    */
    pPager->nRef--;
    assert( pPager->nRef>=0 );
    if( pPager->nRef==0 && !pPager->memDb ){
      pager_reset(pPager);
    }
  }
  return SQLITE_OK;
}

/*
................................................................................
** or EXCLUSIVE lock on the database file when this routine is called.
**
** Return SQLITE_OK if everything.  Return an error code and release the
** write lock if anything goes wrong.
*/
static int pager_open_journal(Pager *pPager){
  int rc;
  assert( !pPager->memDb );
  assert( pPager->state>=PAGER_RESERVED );
  assert( pPager->journalOpen==0 );
  assert( pPager->useJournal );
  sqlite3pager_pagecount(pPager);
  pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 );
  if( pPager->aInJournal==0 ){
    rc = SQLITE_NOMEM;
................................................................................
  PgHdr *pPg = DATA_TO_PGHDR(pData);
  Pager *pPager = pPg->pPager;
  int rc = SQLITE_OK;
  assert( pPg->nRef>0 );
  assert( pPager->state!=PAGER_UNLOCK );
  if( pPager->state==PAGER_SHARED ){
    assert( pPager->aInJournal==0 );
    if( pPager->memDb ){
      pPager->state = PAGER_EXCLUSIVE;
      pPager->origDbSize = pPager->dbSize;
    }else{
      if( SQLITE_BUSY_RESERVED_LOCK || exFlag ){
        rc = pager_wait_on_lock(pPager, RESERVED_LOCK);
      }else{
        rc = sqlite3OsLock(&pPager->fd, RESERVED_LOCK);
................................................................................
  assert( pPager->journalOpen || !pPager->useJournal );
  pPager->dirtyCache = 1;

  /* The transaction journal now exists and we have a RESERVED or an
  ** EXCLUSIVE lock on the main database file.  Write the current page to
  ** the transaction journal if it is not there already.
  */
  if( !pPg->inJournal && (pPager->useJournal || pPager->memDb) ){
    if( (int)pPg->pgno <= pPager->origDbSize ){
      int szPg;
      u32 saved;
      if( pPager->memDb ){
        PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
        TRACE3("JOURNAL %d page %d\n", pPager->fd.h, pPg->pgno);
        assert( pHist->pOrig==0 );
        pHist->pOrig = sqliteMallocRaw( pPager->pageSize );
        if( pHist->pOrig ){
          memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize);
        }
................................................................................
  /* If the statement journal is open and the page is not in it,
  ** then write the current page to the statement journal.  Note that
  ** the statement journal format differs from the standard journal format
  ** in that it omits the checksums and the header.
  */
  if( pPager->stmtInUse && !pPg->inStmt && (int)pPg->pgno<=pPager->stmtSize ){
    assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
    if( pPager->memDb ){
      PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
      assert( pHist->pStmt==0 );
      pHist->pStmt = sqliteMallocRaw( pPager->pageSize );
      if( pHist->pStmt ){
        memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize);
      }
      TRACE3("STMT-JOURNAL %d page %d\n", pPager->fd.h, pPg->pgno);
................................................................................
    page_add_to_stmt_list(pPg);
  }

  /* Update the database size and return.
  */
  if( pPager->dbSize<(int)pPg->pgno ){
    pPager->dbSize = pPg->pgno;
    if( !pPager->memDb && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){
      pPager->dbSize++;
    }
  }
  return rc;
}

/*
................................................................................
** the dont_rollback() routine is called.  But because the page contains
** critical data, we still need to be sure it gets rolled back in spite
** of the dont_rollback() call.
*/
void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){
  PgHdr *pPg;

  if( pPager->memDb ) return;

  pPg = pager_lookup(pPager, pgno);
  pPg->alwaysRollback = 1;
  if( pPg && pPg->dirty ){
    if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){
      /* If this pages is the last page in the file and the file has grown
      ** during the current transaction, then do NOT mark the page as clean.
................................................................................
** rollback journal.
*/
void sqlite3pager_dont_rollback(void *pData){
  PgHdr *pPg = DATA_TO_PGHDR(pData);
  Pager *pPager = pPg->pPager;

  if( pPager->state!=PAGER_EXCLUSIVE || pPager->journalOpen==0 ) return;
  if( pPg->alwaysRollback || pPager->alwaysRollback || pPager->memDb ) return;
  if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){
    assert( pPager->aInJournal!=0 );
    pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
    pPg->inJournal = 1;
    if( pPager->stmtInUse ){
      pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
      page_add_to_stmt_list(pPg);
................................................................................
    rc = pager_errcode(pPager);
    return rc;
  }
  if( pPager->state<PAGER_RESERVED ){
    return SQLITE_ERROR;
  }
  TRACE2("COMMIT %d\n", pPager->fd.h);
  if( pPager->memDb ){
    pPg = pager_get_all_dirty_pages(pPager);
    while( pPg ){
      clearHistory(PGHDR_TO_HIST(pPg, pPager));
      pPg->dirty = 0;
      pPg->inJournal = 0;
      pPg->inStmt = 0;
      pPg->pPrevStmt = pPg->pNextStmt = 0;
................................................................................
** unless a prior malloc() failed (SQLITE_NOMEM).  Appropriate error
** codes are returned for all these occasions.  Otherwise,
** SQLITE_OK is returned.
*/
int sqlite3pager_rollback(Pager *pPager){
  int rc;
  TRACE2("ROLLBACK %d\n", pPager->fd.h);
  if( pPager->memDb ){
    PgHdr *p;
    for(p=pPager->pAll; p; p=p->pNextAll){
      PgHistory *pHist;
      assert( !p->alwaysRollback );
      if( !p->dirty ){
        assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pOrig );
        assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pStmt );
................................................................................
*/
int sqlite3pager_stmt_begin(Pager *pPager){
  int rc;
  char zTemp[SQLITE_TEMPNAME_SIZE];
  assert( !pPager->stmtInUse );
  assert( pPager->dbSize>=0 );
  TRACE2("STMT-BEGIN %d\n", pPager->fd.h);
  if( pPager->memDb ){
    pPager->stmtInUse = 1;
    pPager->stmtSize = pPager->dbSize;
    return SQLITE_OK;
  }
  if( !pPager->journalOpen ){
    pPager->stmtAutoopen = 1;
    return SQLITE_OK;
................................................................................
/*
** Commit a statement.
*/
int sqlite3pager_stmt_commit(Pager *pPager){
  if( pPager->stmtInUse ){
    PgHdr *pPg, *pNext;
    TRACE2("STMT-COMMIT %d\n", pPager->fd.h);
    if( !pPager->memDb ){
      sqlite3OsSeek(&pPager->stfd, 0);
      /* sqlite3OsTruncate(&pPager->stfd, 0); */
      sqliteFree( pPager->aInStmt );
      pPager->aInStmt = 0;
    }
    for(pPg=pPager->pStmt; pPg; pPg=pNext){
      pNext = pPg->pNextStmt;
      assert( pPg->inStmt );
      pPg->inStmt = 0;
      pPg->pPrevStmt = pPg->pNextStmt = 0;
      if( pPager->memDb ){
        PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
        sqliteFree(pHist->pStmt);
        pHist->pStmt = 0;
      }
    }
    pPager->stmtNRec = 0;
    pPager->stmtInUse = 0;
................................................................................
/*
** Rollback a statement.
*/
int sqlite3pager_stmt_rollback(Pager *pPager){
  int rc;
  if( pPager->stmtInUse ){
    TRACE2("STMT-ROLLBACK %d\n", pPager->fd.h);
    if( pPager->memDb ){
      PgHdr *pPg;
      for(pPg=pPager->pStmt; pPg; pPg=pPg->pNextStmt){
        PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
        if( pHist->pStmt ){
          memcpy(PGHDR_TO_DATA(pPg), pHist->pStmt, pPager->pageSize);
          sqliteFree(pHist->pStmt);
          pHist->pStmt = 0;
................................................................................
*/
int sqlite3pager_sync(Pager *pPager, const char *zMaster){
  int rc = SQLITE_OK;

  /* If this is an in-memory db, or no pages have been written to, or this
  ** function has already been called, it is a no-op.
  */
  if( pPager->state!=PAGER_SYNCED && !pPager->memDb && pPager->dirtyCache ){
    PgHdr *pPg;
    assert( pPager->journalOpen );

    /* If a master journal file name has already been written to the
    ** journal file, then no sync is required. This happens when it is
    ** written, then the process fails to upgrade from a RESERVED to an
    ** EXCLUSIVE lock. The next time the process tries to commit the







|







 







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







 







|







 







>




|
>
>







 







|







 







|







 







|







 







|






|











|







 







|







 







|







|



|

|






|







 







|







 







|







 







|







 







|







 







|



|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|










|







 







|







 







|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
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
...
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
....
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
....
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
....
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
....
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
....
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
....
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
....
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
....
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
....
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
....
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
....
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
....
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
....
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
....
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
....
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
....
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
....
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
....
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
....
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
....
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
....
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
....
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.169 2004/10/31 02:22:49 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include "pager.h"
#include <assert.h>
#include <string.h>

................................................................................
/*
** The journal header size for this pager. In the future, this could be
** set to some value read from the disk controller. The important
** characteristic is that it is the same size as a disk sector.
*/
#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize)

/*
** The macro MEMDB is true if we are dealing with an in-memory database.
** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set,
** the value of MEMDB will be a constant and the compiler will optimize
** out code that would never execute.
*/
#ifdef SQLITE_OMIT_MEMORYDB
# define MEMDB 0
#else
# define MEMDB pPager->memDb
#endif

/*
** The default size of a disk sector
*/
#define PAGER_SECTOR_SIZE 512

/*
** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is
** reserved for working around a windows/posix incompatibility). It is
** used in the journal to signify that the remainder of the journal file 
** is devoted to storing a master journal name - there are no more pages to
................................................................................
** TODO: Consider keeping the journal file open for temporary databases.
** This might give a performance improvement on windows where opening
** a file is an expensive operation.
*/
static int pager_unwritelock(Pager *pPager){
  PgHdr *pPg;
  int rc;
  assert( !MEMDB );
  if( pPager->state<PAGER_RESERVED ){
    return SQLITE_OK;
  }
  sqlite3pager_stmt_commit(pPager);
  if( pPager->stmtOpen ){
    sqlite3OsClose(&pPager->stfd);
    pPager->stmtOpen = 0;
................................................................................

  *ppPager = 0;
  memset(&fd, 0, sizeof(fd));
  if( sqlite3_malloc_failed ){
    return SQLITE_NOMEM;
  }
  if( zFilename && zFilename[0] ){
#ifndef SQLITE_OMIT_MEMORYDB
    if( strcmp(zFilename,":memory:")==0 ){
      memDb = 1;
      zFullPathname = sqliteStrDup("");
      rc = SQLITE_OK;
    }else
#endif
    {
      zFullPathname = sqlite3OsFullPathname(zFilename);
      if( zFullPathname ){
        rc = sqlite3OsOpenReadWrite(zFullPathname, &fd, &readOnly);
      }
    }
  }else{
    rc = sqlite3pager_opentemp(zTemp, &fd);
................................................................................

/*
** Read the first N bytes from the beginning of the file into memory
** that pDest points to.  No error checking is done.
*/
void sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){
  memset(pDest, 0, N);
  if( MEMDB==0 ){
    sqlite3OsSeek(&pPager->fd, 0);
    sqlite3OsRead(&pPager->fd, pDest, N);
  }
}

/*
** Return the total number of pages in the disk file associated with
................................................................................
    return pPager->dbSize;
  }
  if( sqlite3OsFileSize(&pPager->fd, &n)!=SQLITE_OK ){
    pPager->errMask |= PAGER_ERR_DISK;
    return 0;
  }
  n /= pPager->pageSize;
  if( !MEMDB && n==PENDING_BYTE/pPager->pageSize ){
    n++;
  }
  if( pPager->state!=PAGER_UNLOCK ){
    pPager->dbSize = n;
  }
  return n;
}
................................................................................
  if( pPager->errMask!=0 ){
    rc = pager_errcode(pPager);
    return rc;
  }
  if( nPage>=(unsigned)pPager->dbSize ){
    return SQLITE_OK;
  }
  if( MEMDB ){
    pPager->dbSize = nPage;
    memoryTruncate(pPager);
    return SQLITE_OK;
  }
  rc = syncJournal(pPager);
  if( rc!=SQLITE_OK ){
    return rc;
................................................................................
int sqlite3pager_close(Pager *pPager){
  PgHdr *pPg, *pNext;
  switch( pPager->state ){
    case PAGER_RESERVED:
    case PAGER_SYNCED: 
    case PAGER_EXCLUSIVE: {
      sqlite3pager_rollback(pPager);
      if( !MEMDB ){
        sqlite3OsUnlock(&pPager->fd, NO_LOCK);
      }
      assert( pPager->journalOpen==0 );
      break;
    }
    case PAGER_SHARED: {
      if( !MEMDB ){
        sqlite3OsUnlock(&pPager->fd, NO_LOCK);
      }
      break;
    }
    default: {
      /* Do nothing */
      break;
    }
  }
  for(pPg=pPager->pAll; pPg; pPg=pNext){
#ifndef NDEBUG
    if( MEMDB ){
      PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
      assert( !pPg->alwaysRollback );
      assert( !pHist->pOrig );
      assert( !pHist->pStmt );
    }
#endif
    pNext = pPg->pNextAll;
................................................................................
  if( pPager->errMask & ~(PAGER_ERR_FULL) ){
    return pager_errcode(pPager);
  }

  /* If this is the first page accessed, then get a SHARED lock
  ** on the database file.
  */
  if( pPager->nRef==0 && !MEMDB ){
    rc = pager_wait_on_lock(pPager, SHARED_LOCK);
    if( rc!=SQLITE_OK ){
      return rc;
    }

    /* If a journal file exists, and there is no RESERVED lock on the
    ** database file, then it either needs to be played back or deleted.
................................................................................
         return rc;
       }
    }
    pPg = 0;
  }else{
    /* Search for page in cache */
    pPg = pager_lookup(pPager, pgno);
    if( MEMDB && pPager->state==PAGER_UNLOCK ){
      pPager->state = PAGER_SHARED;
    }
  }
  if( pPg==0 ){
    /* The requested page is not in the page cache. */
    int h;
    pPager->nMiss++;
    if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 || MEMDB ){
      /* Create a new page */
      pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->psAligned
                              + sizeof(u32) + pPager->nExtra
                              + MEMDB*sizeof(PgHistory) );
      if( pPg==0 ){
        if( !MEMDB ){
          pager_unwritelock(pPager);
        }
        pPager->errMask |= PAGER_ERR_MEM;
        return SQLITE_NOMEM;
      }
      memset(pPg, 0, sizeof(*pPg));
      if( MEMDB ){
        memset(PGHDR_TO_HIST(pPg, pPager), 0, sizeof(PgHistory));
      }
      pPg->pPager = pPager;
      pPg->pNextAll = pPager->pAll;
      pPager->pAll = pPg;
      pPager->nPage++;
    }else{
................................................................................
      rc = pager_errcode(pPager);
      return rc;
    }
    if( pPager->dbSize<(int)pgno ){
      memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
    }else{
      int rc;
      assert( MEMDB==0 );
      sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize);
      rc = sqlite3OsRead(&pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize);
      TRACE3("FETCH %d page %d\n", pPager->fd.h, pPg->pgno);
      CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
      if( rc!=SQLITE_OK ){
        i64 fileSize;
        if( sqlite3OsFileSize(&pPager->fd,&fileSize)!=SQLITE_OK
................................................................................
    }
  
    /* When all pages reach the freelist, drop the read lock from
    ** the database file.
    */
    pPager->nRef--;
    assert( pPager->nRef>=0 );
    if( pPager->nRef==0 && !MEMDB ){
      pager_reset(pPager);
    }
  }
  return SQLITE_OK;
}

/*
................................................................................
** or EXCLUSIVE lock on the database file when this routine is called.
**
** Return SQLITE_OK if everything.  Return an error code and release the
** write lock if anything goes wrong.
*/
static int pager_open_journal(Pager *pPager){
  int rc;
  assert( !MEMDB );
  assert( pPager->state>=PAGER_RESERVED );
  assert( pPager->journalOpen==0 );
  assert( pPager->useJournal );
  sqlite3pager_pagecount(pPager);
  pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 );
  if( pPager->aInJournal==0 ){
    rc = SQLITE_NOMEM;
................................................................................
  PgHdr *pPg = DATA_TO_PGHDR(pData);
  Pager *pPager = pPg->pPager;
  int rc = SQLITE_OK;
  assert( pPg->nRef>0 );
  assert( pPager->state!=PAGER_UNLOCK );
  if( pPager->state==PAGER_SHARED ){
    assert( pPager->aInJournal==0 );
    if( MEMDB ){
      pPager->state = PAGER_EXCLUSIVE;
      pPager->origDbSize = pPager->dbSize;
    }else{
      if( SQLITE_BUSY_RESERVED_LOCK || exFlag ){
        rc = pager_wait_on_lock(pPager, RESERVED_LOCK);
      }else{
        rc = sqlite3OsLock(&pPager->fd, RESERVED_LOCK);
................................................................................
  assert( pPager->journalOpen || !pPager->useJournal );
  pPager->dirtyCache = 1;

  /* The transaction journal now exists and we have a RESERVED or an
  ** EXCLUSIVE lock on the main database file.  Write the current page to
  ** the transaction journal if it is not there already.
  */
  if( !pPg->inJournal && (pPager->useJournal || MEMDB) ){
    if( (int)pPg->pgno <= pPager->origDbSize ){
      int szPg;
      u32 saved;
      if( MEMDB ){
        PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
        TRACE3("JOURNAL %d page %d\n", pPager->fd.h, pPg->pgno);
        assert( pHist->pOrig==0 );
        pHist->pOrig = sqliteMallocRaw( pPager->pageSize );
        if( pHist->pOrig ){
          memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize);
        }
................................................................................
  /* If the statement journal is open and the page is not in it,
  ** then write the current page to the statement journal.  Note that
  ** the statement journal format differs from the standard journal format
  ** in that it omits the checksums and the header.
  */
  if( pPager->stmtInUse && !pPg->inStmt && (int)pPg->pgno<=pPager->stmtSize ){
    assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
    if( MEMDB ){
      PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
      assert( pHist->pStmt==0 );
      pHist->pStmt = sqliteMallocRaw( pPager->pageSize );
      if( pHist->pStmt ){
        memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize);
      }
      TRACE3("STMT-JOURNAL %d page %d\n", pPager->fd.h, pPg->pgno);
................................................................................
    page_add_to_stmt_list(pPg);
  }

  /* Update the database size and return.
  */
  if( pPager->dbSize<(int)pPg->pgno ){
    pPager->dbSize = pPg->pgno;
    if( !MEMDB && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){
      pPager->dbSize++;
    }
  }
  return rc;
}

/*
................................................................................
** the dont_rollback() routine is called.  But because the page contains
** critical data, we still need to be sure it gets rolled back in spite
** of the dont_rollback() call.
*/
void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){
  PgHdr *pPg;

  if( MEMDB ) return;

  pPg = pager_lookup(pPager, pgno);
  pPg->alwaysRollback = 1;
  if( pPg && pPg->dirty ){
    if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){
      /* If this pages is the last page in the file and the file has grown
      ** during the current transaction, then do NOT mark the page as clean.
................................................................................
** rollback journal.
*/
void sqlite3pager_dont_rollback(void *pData){
  PgHdr *pPg = DATA_TO_PGHDR(pData);
  Pager *pPager = pPg->pPager;

  if( pPager->state!=PAGER_EXCLUSIVE || pPager->journalOpen==0 ) return;
  if( pPg->alwaysRollback || pPager->alwaysRollback || MEMDB ) return;
  if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){
    assert( pPager->aInJournal!=0 );
    pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
    pPg->inJournal = 1;
    if( pPager->stmtInUse ){
      pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
      page_add_to_stmt_list(pPg);
................................................................................
    rc = pager_errcode(pPager);
    return rc;
  }
  if( pPager->state<PAGER_RESERVED ){
    return SQLITE_ERROR;
  }
  TRACE2("COMMIT %d\n", pPager->fd.h);
  if( MEMDB ){
    pPg = pager_get_all_dirty_pages(pPager);
    while( pPg ){
      clearHistory(PGHDR_TO_HIST(pPg, pPager));
      pPg->dirty = 0;
      pPg->inJournal = 0;
      pPg->inStmt = 0;
      pPg->pPrevStmt = pPg->pNextStmt = 0;
................................................................................
** unless a prior malloc() failed (SQLITE_NOMEM).  Appropriate error
** codes are returned for all these occasions.  Otherwise,
** SQLITE_OK is returned.
*/
int sqlite3pager_rollback(Pager *pPager){
  int rc;
  TRACE2("ROLLBACK %d\n", pPager->fd.h);
  if( MEMDB ){
    PgHdr *p;
    for(p=pPager->pAll; p; p=p->pNextAll){
      PgHistory *pHist;
      assert( !p->alwaysRollback );
      if( !p->dirty ){
        assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pOrig );
        assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pStmt );
................................................................................
*/
int sqlite3pager_stmt_begin(Pager *pPager){
  int rc;
  char zTemp[SQLITE_TEMPNAME_SIZE];
  assert( !pPager->stmtInUse );
  assert( pPager->dbSize>=0 );
  TRACE2("STMT-BEGIN %d\n", pPager->fd.h);
  if( MEMDB ){
    pPager->stmtInUse = 1;
    pPager->stmtSize = pPager->dbSize;
    return SQLITE_OK;
  }
  if( !pPager->journalOpen ){
    pPager->stmtAutoopen = 1;
    return SQLITE_OK;
................................................................................
/*
** Commit a statement.
*/
int sqlite3pager_stmt_commit(Pager *pPager){
  if( pPager->stmtInUse ){
    PgHdr *pPg, *pNext;
    TRACE2("STMT-COMMIT %d\n", pPager->fd.h);
    if( !MEMDB ){
      sqlite3OsSeek(&pPager->stfd, 0);
      /* sqlite3OsTruncate(&pPager->stfd, 0); */
      sqliteFree( pPager->aInStmt );
      pPager->aInStmt = 0;
    }
    for(pPg=pPager->pStmt; pPg; pPg=pNext){
      pNext = pPg->pNextStmt;
      assert( pPg->inStmt );
      pPg->inStmt = 0;
      pPg->pPrevStmt = pPg->pNextStmt = 0;
      if( MEMDB ){
        PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
        sqliteFree(pHist->pStmt);
        pHist->pStmt = 0;
      }
    }
    pPager->stmtNRec = 0;
    pPager->stmtInUse = 0;
................................................................................
/*
** Rollback a statement.
*/
int sqlite3pager_stmt_rollback(Pager *pPager){
  int rc;
  if( pPager->stmtInUse ){
    TRACE2("STMT-ROLLBACK %d\n", pPager->fd.h);
    if( MEMDB ){
      PgHdr *pPg;
      for(pPg=pPager->pStmt; pPg; pPg=pPg->pNextStmt){
        PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
        if( pHist->pStmt ){
          memcpy(PGHDR_TO_DATA(pPg), pHist->pStmt, pPager->pageSize);
          sqliteFree(pHist->pStmt);
          pHist->pStmt = 0;
................................................................................
*/
int sqlite3pager_sync(Pager *pPager, const char *zMaster){
  int rc = SQLITE_OK;

  /* If this is an in-memory db, or no pages have been written to, or this
  ** function has already been called, it is a no-op.
  */
  if( pPager->state!=PAGER_SYNCED && !MEMDB && pPager->dirtyCache ){
    PgHdr *pPg;
    assert( pPager->journalOpen );

    /* If a master journal file name has already been written to the
    ** journal file, then no sync is required. This happens when it is
    ** written, then the process fails to upgrade from a RESERVED to an
    ** EXCLUSIVE lock. The next time the process tries to commit the

Changes to src/parse.y.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
77
78
79
80
81
82
83
84
85

86

87
88

89
90
91
92
93
94
95
...
140
141
142
143
144
145
146
147




148
149
150
151
152
153
154
...
281
282
283
284
285
286
287

288
289
290
291
292
293

294
295
296
297
298
299
300
...
301
302
303
304
305
306
307

308
309
310
311
312
313
314
315
316
317
318
319

320
321
322
323
324
325
326
...
788
789
790
791
792
793
794


795
796
797
798
799
800
801
...
865
866
867
868
869
870
871


872
873
874
875
876
877
878

879
880
881

882
883
884
885
886
887
888
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.144 2004/10/07 03:06:29 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  if( pParse->zErrMsg==0 ){
................................................................................
%nonassoc END_OF_FILE ILLEGAL SPACE UNCLOSED_STRING COMMENT FUNCTION
          COLUMN AGG_FUNCTION.

// Input is a single SQL command
input ::= cmdlist.
cmdlist ::= cmdlist ecmd.
cmdlist ::= ecmd.
ecmd ::= explain cmdx SEMI.
ecmd ::= SEMI.

cmdx ::= cmd.           { sqlite3FinishCoding(pParse); }

explain ::= EXPLAIN.    { sqlite3BeginParse(pParse, 1); }
explain ::= .           { sqlite3BeginParse(pParse, 0); }


///////////////////// Begin and end transactions. ////////////////////////////
//

cmd ::= BEGIN transtype(Y) trans_opt.  {sqlite3BeginTransaction(pParse, Y);}
trans_opt ::= .
trans_opt ::= TRANSACTION.
................................................................................
// This obviates the need for the "id" nonterminal.
//
%fallback ID
  ABORT AFTER ASC ATTACH BEFORE BEGIN CASCADE CONFLICT
  DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
  GLOB IGNORE IMMEDIATE INITIALLY INSTEAD LIKE MATCH KEY
  OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW STATEMENT
  TEMP TRIGGER VACUUM VIEW.





// Define operator precedence early so that this is the first occurance
// of the operator tokens in the grammer.  Keeping the operators together
// causes them to be assigned integer values that are close together,
// which keeps parser tables smaller.
//
// The token values assigned to these symbols is determined by the order
................................................................................
//
cmd ::= DROP TABLE fullname(X). {
  sqlite3DropTable(pParse, X, 0);
}

///////////////////// The CREATE VIEW statement /////////////////////////////
//

cmd ::= CREATE(X) temp(T) VIEW nm(Y) dbnm(Z) AS select(S). {
  sqlite3CreateView(pParse, &X, &Y, &Z, S, T);
}
cmd ::= DROP VIEW fullname(X). {
  sqlite3DropTable(pParse, X, 1);
}


//////////////////////// The SELECT statement /////////////////////////////////
//
cmd ::= select(X).  {
  sqlite3Select(pParse, X, SRT_Callback, 0, 0, 0, 0, 0);
  sqlite3SelectDelete(X);
}
................................................................................

%type select {Select*}
%destructor select {sqlite3SelectDelete($$);}
%type oneselect {Select*}
%destructor oneselect {sqlite3SelectDelete($$);}

select(A) ::= oneselect(X).                      {A = X;}

select(A) ::= select(X) multiselect_op(Y) oneselect(Z).  {
  if( Z ){
    Z->op = Y;
    Z->pPrior = X;
  }
  A = Z;
}
%type multiselect_op {int}
multiselect_op(A) ::= UNION(OP).      {A = @OP;}
multiselect_op(A) ::= UNION ALL.      {A = TK_ALL;}
multiselect_op(A) ::= INTERSECT(OP).  {A = @OP;}
multiselect_op(A) ::= EXCEPT(OP).     {A = @OP;}

oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y)
                 groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). {
  A = sqlite3SelectNew(W,X,Y,P,Q,Z,D,L.limit,L.offset);
}

// The "distinct" nonterminal is true (1) if the DISTINCT keyword is
// present and false (0) if it is not.
................................................................................
minus_num(A) ::= MINUS number(X).     {A = X;}
number(A) ::= INTEGER(X).             {A = X;}
number(A) ::= FLOAT(X).               {A = X;}
plus_opt ::= PLUS.
plus_opt ::= .

//////////////////////////// The CREATE TRIGGER command /////////////////////



cmd ::= CREATE trigger_decl(A) BEGIN trigger_cmd_list(S) END(Z). {
  Token all;
  all.z = A.z;
  all.n = (Z.z - A.z) + Z.n;
  sqlite3FinishTrigger(pParse, S, &all);
}
................................................................................
  sqlite3ExprSpan(A, &X, &Y);
}
expr(A) ::= RAISE(X) LP raisetype(T) COMMA nm(Z) RP(Y).  {
  A = sqlite3Expr(TK_RAISE, 0, 0, &Z); 
  A->iColumn = T;
  sqlite3ExprSpan(A, &X, &Y);
}


%type raisetype {int}
raisetype(A) ::= ROLLBACK.  {A = OE_Rollback;}
raisetype(A) ::= ABORT.     {A = OE_Abort;}
raisetype(A) ::= FAIL.      {A = OE_Fail;}


////////////////////////  DROP TRIGGER statement //////////////////////////////

cmd ::= DROP TRIGGER fullname(X). {
  sqlite3DropTrigger(pParse,X);
}


//////////////////////// ATTACH DATABASE file AS name /////////////////////////
cmd ::= ATTACH database_kw_opt ids(F) AS nm(D) key_opt(K). {
  sqlite3Attach(pParse, &F, &D, K.type, &K.key);
}
%type key_opt {struct AttachKey}
key_opt(A) ::= .                     { A.type = 0; }







|







 







|

>
|
>

<
>







 







|
>
>
>
>







 







>






>







 







>












>







 







>
>







 







>
>







>



>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
77
78
79
80
81
82
83
84
85
86
87
88
89

90
91
92
93
94
95
96
97
...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
...
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
...
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
...
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
...
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.145 2004/10/31 02:22:49 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  if( pParse->zErrMsg==0 ){
................................................................................
%nonassoc END_OF_FILE ILLEGAL SPACE UNCLOSED_STRING COMMENT FUNCTION
          COLUMN AGG_FUNCTION.

// Input is a single SQL command
input ::= cmdlist.
cmdlist ::= cmdlist ecmd.
cmdlist ::= ecmd.
cmdx ::= cmd.           { sqlite3FinishCoding(pParse); }
ecmd ::= SEMI.
ecmd ::= explain cmdx SEMI.
explain ::= .           { sqlite3BeginParse(pParse, 0); }
%ifndef SQLITE_OMIT_EXPLAIN
explain ::= EXPLAIN.    { sqlite3BeginParse(pParse, 1); }

%endif

///////////////////// Begin and end transactions. ////////////////////////////
//

cmd ::= BEGIN transtype(Y) trans_opt.  {sqlite3BeginTransaction(pParse, Y);}
trans_opt ::= .
trans_opt ::= TRANSACTION.
................................................................................
// This obviates the need for the "id" nonterminal.
//
%fallback ID
  ABORT AFTER ASC ATTACH BEFORE BEGIN CASCADE CONFLICT
  DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
  GLOB IGNORE IMMEDIATE INITIALLY INSTEAD LIKE MATCH KEY
  OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW STATEMENT
  TEMP TRIGGER VACUUM VIEW
%ifdef SQLITE_OMIT_COMPOUND_SELECT
  EXCEPT INTERSECT UNION
%endif
  .

// Define operator precedence early so that this is the first occurance
// of the operator tokens in the grammer.  Keeping the operators together
// causes them to be assigned integer values that are close together,
// which keeps parser tables smaller.
//
// The token values assigned to these symbols is determined by the order
................................................................................
//
cmd ::= DROP TABLE fullname(X). {
  sqlite3DropTable(pParse, X, 0);
}

///////////////////// The CREATE VIEW statement /////////////////////////////
//
%ifndef SQLITE_OMIT_VIEW
cmd ::= CREATE(X) temp(T) VIEW nm(Y) dbnm(Z) AS select(S). {
  sqlite3CreateView(pParse, &X, &Y, &Z, S, T);
}
cmd ::= DROP VIEW fullname(X). {
  sqlite3DropTable(pParse, X, 1);
}
%endif // SQLITE_OMIT_VIEW

//////////////////////// The SELECT statement /////////////////////////////////
//
cmd ::= select(X).  {
  sqlite3Select(pParse, X, SRT_Callback, 0, 0, 0, 0, 0);
  sqlite3SelectDelete(X);
}
................................................................................

%type select {Select*}
%destructor select {sqlite3SelectDelete($$);}
%type oneselect {Select*}
%destructor oneselect {sqlite3SelectDelete($$);}

select(A) ::= oneselect(X).                      {A = X;}
%ifndef SQLITE_OMIT_COMPOUND_SELECT
select(A) ::= select(X) multiselect_op(Y) oneselect(Z).  {
  if( Z ){
    Z->op = Y;
    Z->pPrior = X;
  }
  A = Z;
}
%type multiselect_op {int}
multiselect_op(A) ::= UNION(OP).      {A = @OP;}
multiselect_op(A) ::= UNION ALL.      {A = TK_ALL;}
multiselect_op(A) ::= INTERSECT(OP).  {A = @OP;}
multiselect_op(A) ::= EXCEPT(OP).     {A = @OP;}
%endif // SQLITE_OMIT_COMPOUND_SELECT
oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y)
                 groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). {
  A = sqlite3SelectNew(W,X,Y,P,Q,Z,D,L.limit,L.offset);
}

// The "distinct" nonterminal is true (1) if the DISTINCT keyword is
// present and false (0) if it is not.
................................................................................
minus_num(A) ::= MINUS number(X).     {A = X;}
number(A) ::= INTEGER(X).             {A = X;}
number(A) ::= FLOAT(X).               {A = X;}
plus_opt ::= PLUS.
plus_opt ::= .

//////////////////////////// The CREATE TRIGGER command /////////////////////

%ifndef SQLITE_OMIT_TRIGGER

cmd ::= CREATE trigger_decl(A) BEGIN trigger_cmd_list(S) END(Z). {
  Token all;
  all.z = A.z;
  all.n = (Z.z - A.z) + Z.n;
  sqlite3FinishTrigger(pParse, S, &all);
}
................................................................................
  sqlite3ExprSpan(A, &X, &Y);
}
expr(A) ::= RAISE(X) LP raisetype(T) COMMA nm(Z) RP(Y).  {
  A = sqlite3Expr(TK_RAISE, 0, 0, &Z); 
  A->iColumn = T;
  sqlite3ExprSpan(A, &X, &Y);
}
%endif // !SQLITE_OMIT_TRIGGER

%type raisetype {int}
raisetype(A) ::= ROLLBACK.  {A = OE_Rollback;}
raisetype(A) ::= ABORT.     {A = OE_Abort;}
raisetype(A) ::= FAIL.      {A = OE_Fail;}


////////////////////////  DROP TRIGGER statement //////////////////////////////
%ifndef SQLITE_OMIT_TRIGGER
cmd ::= DROP TRIGGER fullname(X). {
  sqlite3DropTrigger(pParse,X);
}
%endif // !SQLITE_OMIT_TRIGGER

//////////////////////// ATTACH DATABASE file AS name /////////////////////////
cmd ::= ATTACH database_kw_opt ids(F) AS nm(D) key_opt(K). {
  sqlite3Attach(pParse, &F, &D, K.type, &K.key);
}
%type key_opt {struct AttachKey}
key_opt(A) ::= .                     { A.type = 0; }

Changes to src/pragma.c.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
440
441
442
443
444
445
446

447
448
449
450
451
452
453
...
473
474
475
476
477
478
479

480
481
482
483
484
485
486
...
503
504
505
506
507
508
509

510
511
512
513
514
515
516
...
627
628
629
630
631
632
633


634
635
636
637
638
639
640
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.72 2004/10/25 20:33:44 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
# include "pager.h"
# include "btree.h"
................................................................................
          ++i;
          pIdx = pIdx->pNext;
        }
      }
    }
  }else


  if( sqlite3StrICmp(zLeft, "foreign_key_list")==0 && zRight ){
    FKey *pFK;
    Table *pTab;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    pTab = sqlite3FindTable(db, zRight, zDb);
    if( pTab ){
      v = sqlite3GetVdbe(pParse);
................................................................................
          }
          ++i;
          pFK = pFK->pNextFrom;
        }
      }
    }
  }else


  if( sqlite3StrICmp(zLeft, "database_list")==0 ){
    int i;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    sqlite3VdbeSetNumCols(v, 3);
    sqlite3VdbeSetColName(v, 0, "seq", P3_STATIC);
    sqlite3VdbeSetColName(v, 1, "name", P3_STATIC);
................................................................................
      sqlite3ParserTrace(stdout, "parser: ");
    }else{
      sqlite3ParserTrace(0, 0);
    }
  }else
#endif


  if( sqlite3StrICmp(zLeft, "integrity_check")==0 ){
    int i, j, addr;

    /* Code that initializes the integrity check program.  Set the
    ** error count 0
    */
    static const VdbeOpList initCode[] = {
................................................................................
          sqlite3VdbeChangeP3(v, addr+10, pIdx->zName, P3_STATIC);
        }
      } 
    }
    addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode);
    sqlite3VdbeChangeP2(v, addr+2, addr+ArraySize(endCode));
  }else


  /*
  **   PRAGMA encoding
  **   PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be"
  **
  ** In it's first form, this pragma returns the encoding of the main
  ** database. If the database is not initialized, it is initialized now.
  **







|







 







>







 







>







 







>







 







>
>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
...
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
...
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
...
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.73 2004/10/31 02:22:49 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
# include "pager.h"
# include "btree.h"
................................................................................
          ++i;
          pIdx = pIdx->pNext;
        }
      }
    }
  }else

#ifndef SQLITE_OMIT_FOREIGN_KEY
  if( sqlite3StrICmp(zLeft, "foreign_key_list")==0 && zRight ){
    FKey *pFK;
    Table *pTab;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    pTab = sqlite3FindTable(db, zRight, zDb);
    if( pTab ){
      v = sqlite3GetVdbe(pParse);
................................................................................
          }
          ++i;
          pFK = pFK->pNextFrom;
        }
      }
    }
  }else
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */

  if( sqlite3StrICmp(zLeft, "database_list")==0 ){
    int i;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    sqlite3VdbeSetNumCols(v, 3);
    sqlite3VdbeSetColName(v, 0, "seq", P3_STATIC);
    sqlite3VdbeSetColName(v, 1, "name", P3_STATIC);
................................................................................
      sqlite3ParserTrace(stdout, "parser: ");
    }else{
      sqlite3ParserTrace(0, 0);
    }
  }else
#endif

#ifndef SQLITE_OMIT_INTEGRITY_CHECK
  if( sqlite3StrICmp(zLeft, "integrity_check")==0 ){
    int i, j, addr;

    /* Code that initializes the integrity check program.  Set the
    ** error count 0
    */
    static const VdbeOpList initCode[] = {
................................................................................
          sqlite3VdbeChangeP3(v, addr+10, pIdx->zName, P3_STATIC);
        }
      } 
    }
    addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode);
    sqlite3VdbeChangeP2(v, addr+2, addr+ArraySize(endCode));
  }else
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

  /*
  **   PRAGMA encoding
  **   PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be"
  **
  ** In it's first form, this pragma returns the encoding of the main
  ** database. If the database is not initialized, it is initialized now.
  **

Changes to src/select.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1278
1279
1280
1281
1282
1283
1284

1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296

1297

1298
1299
1300
1301
1302
1303
1304
....
1311
1312
1313
1314
1315
1316
1317

1318

1319
1320
1321
1322
1323
1324
1325
....
1700
1701
1702
1703
1704
1705
1706

1707

1708
1709
1710
1711
1712
1713
1714
....
1753
1754
1755
1756
1757
1758
1759

1760

1761
1762
1763
1764
1765
1766
1767
....
2005
2006
2007
2008
2009
2010
2011

2012
2013
2014
2015
2016
2017
2018
....
2258
2259
2260
2261
2262
2263
2264

2265
2266
2267
2268
2269

2270
2271
2272
2273
2274
2275
2276
....
2396
2397
2398
2399
2400
2401
2402

2403
2404
2405
2406
2407

2408
2409
2410
2411
2412
2413
2414
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.212 2004/10/06 15:41:17 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
................................................................................
      (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
  if( keyAsData ){
    sqlite3VdbeAddOp(v, OP_KeyAsData, iTab, 1);
  }
  return addr;
}


/*
** Add the address "addr" to the set of all OpenTemp opcode addresses
** that are being accumulated in p->ppOpenTemp.
*/
static int multiSelectOpenTempAddr(Select *p, int addr){
  IdList *pList = *p->ppOpenTemp = sqlite3IdListAppend(*p->ppOpenTemp, 0);
  if( pList==0 ){
    return SQLITE_NOMEM;
  }
  pList->a[pList->nId-1].idx = addr;
  return SQLITE_OK;
}



/*
** Return the appropriate collating sequence for the iCol-th column of
** the result set for the compound-select statement "p".  Return NULL if
** the column has no default collating sequence.
**
** The collating sequence for the compound select is taken from the
** left-most term of the select that has a collating sequence.
................................................................................
    pRet = 0;
  }
  if( pRet==0 ){
    pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr);
  }
  return pRet;
}



/*
** This routine is called to process a query that is really the union
** or intersection of two or more separate queries.
**
** "p" points to the right-most of the two queries.  the query on the
** left is p->pPrior.  The left query could also be a compound query
** in which case this routine will be called recursively. 
................................................................................
multi_select_end:
  if( pOpenTemp ){
    sqlite3IdListDelete(pOpenTemp);
  }
  p->ppOpenTemp = 0;
  return rc;
}



/*
** Scan through the expression pExpr.  Replace every reference to
** a column in table number iTable with a copy of the iColumn-th
** entry in pEList.  (But leave references to the ROWID column 
** unchanged.)
**
** This routine is part of the flattening procedure.  A subquery
................................................................................
substExprList(ExprList *pList, int iTable, ExprList *pEList){
  int i;
  if( pList==0 ) return;
  for(i=0; i<pList->nExpr; i++){
    substExpr(pList->a[i].pExpr, iTable, pEList);
  }
}



/*
** This routine attempts to flatten subqueries in order to speed
** execution.  It returns 1 if it makes changes and 0 if no flattening
** occurs.
**
** To understand the concept of flattening, consider the following
** query:
................................................................................

  /* Finially, delete what is left of the subquery and return
  ** success.
  */
  sqlite3SelectDelete(pSub);
  return 1;
}


/*
** Analyze the SELECT statement passed in as an argument to see if it
** is a simple min() or max() query.  If it is and this query can be
** satisfied using a single seek to the beginning or end of an index,
** then generate the code for this SELECT and return 1.  If this is not a 
** simple min() or max() query, then return 0;
................................................................................
  int isDistinct;        /* True if the DISTINCT keyword is present */
  int distinct;          /* Table to use for the distinct set */
  int rc = 1;            /* Value to return from this function */

  if( sqlite3_malloc_failed || pParse->nErr || p==0 ) return 1;
  if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;


  /* If there is are a sequence of queries, do the earlier ones first.
  */
  if( p->pPrior ){
    return multiSelect(pParse, p, eDest, iParm, aff);
  }


  /* Make local copies of the parameters for this query.
  */
  pTabList = p->pSrc;
  pWhere = p->pWhere;
  pOrderBy = p->pOrderBy;
  pGroupBy = p->pGroupBy;
................................................................................
    rc = 0;
    goto select_end;
  }

  /* Check to see if this is a subquery that can be "flattened" into its parent.
  ** If flattening is a possiblity, do so and return immediately.  
  */

  if( pParent && pParentAgg &&
      flattenSubquery(pParse, pParent, parentTab, *pParentAgg, isAgg) ){
    if( isAgg ) *pParentAgg = 1;
    return rc;
  }


  /* If there is an ORDER BY clause, resolve any collation sequences
  ** names that have been explicitly specified.
  */
  if( pOrderBy ){
    for(i=0; i<pOrderBy->nExpr; i++){
      if( pOrderBy->a[i].zName ){







|







 







>












>

>







 







>

>







 







>

>







 







>

>







 







>







 







>





>







 







>





>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
....
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
....
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
....
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
....
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
....
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
....
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.213 2004/10/31 02:22:49 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
................................................................................
      (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
  if( keyAsData ){
    sqlite3VdbeAddOp(v, OP_KeyAsData, iTab, 1);
  }
  return addr;
}

#ifndef SQLITE_OMIT_COMPOUND_SELECT
/*
** Add the address "addr" to the set of all OpenTemp opcode addresses
** that are being accumulated in p->ppOpenTemp.
*/
static int multiSelectOpenTempAddr(Select *p, int addr){
  IdList *pList = *p->ppOpenTemp = sqlite3IdListAppend(*p->ppOpenTemp, 0);
  if( pList==0 ){
    return SQLITE_NOMEM;
  }
  pList->a[pList->nId-1].idx = addr;
  return SQLITE_OK;
}
#endif /* SQLITE_OMIT_COMPOUND_SELECT */

#ifndef SQLITE_OMIT_COMPOUND_SELECT
/*
** Return the appropriate collating sequence for the iCol-th column of
** the result set for the compound-select statement "p".  Return NULL if
** the column has no default collating sequence.
**
** The collating sequence for the compound select is taken from the
** left-most term of the select that has a collating sequence.
................................................................................
    pRet = 0;
  }
  if( pRet==0 ){
    pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr);
  }
  return pRet;
}
#endif /* SQLITE_OMIT_COMPOUND_SELECT */

#ifndef SQLITE_OMIT_COMPOUND_SELECT
/*
** This routine is called to process a query that is really the union
** or intersection of two or more separate queries.
**
** "p" points to the right-most of the two queries.  the query on the
** left is p->pPrior.  The left query could also be a compound query
** in which case this routine will be called recursively. 
................................................................................
multi_select_end:
  if( pOpenTemp ){
    sqlite3IdListDelete(pOpenTemp);
  }
  p->ppOpenTemp = 0;
  return rc;
}
#endif /* SQLITE_OMIT_COMPOUND_SELECT */

#ifndef SQLITE_OMIT_VIEW
/*
** Scan through the expression pExpr.  Replace every reference to
** a column in table number iTable with a copy of the iColumn-th
** entry in pEList.  (But leave references to the ROWID column 
** unchanged.)
**
** This routine is part of the flattening procedure.  A subquery
................................................................................
substExprList(ExprList *pList, int iTable, ExprList *pEList){
  int i;
  if( pList==0 ) return;
  for(i=0; i<pList->nExpr; i++){
    substExpr(pList->a[i].pExpr, iTable, pEList);
  }
}
#endif /* !defined(SQLITE_OMIT_VIEW) */

#ifndef SQLITE_OMIT_VIEW
/*
** This routine attempts to flatten subqueries in order to speed
** execution.  It returns 1 if it makes changes and 0 if no flattening
** occurs.
**
** To understand the concept of flattening, consider the following
** query:
................................................................................

  /* Finially, delete what is left of the subquery and return
  ** success.
  */
  sqlite3SelectDelete(pSub);
  return 1;
}
#endif /* SQLITE_OMIT_VIEW */

/*
** Analyze the SELECT statement passed in as an argument to see if it
** is a simple min() or max() query.  If it is and this query can be
** satisfied using a single seek to the beginning or end of an index,
** then generate the code for this SELECT and return 1.  If this is not a 
** simple min() or max() query, then return 0;
................................................................................
  int isDistinct;        /* True if the DISTINCT keyword is present */
  int distinct;          /* Table to use for the distinct set */
  int rc = 1;            /* Value to return from this function */

  if( sqlite3_malloc_failed || pParse->nErr || p==0 ) return 1;
  if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;

#ifndef SQLITE_OMIT_COMPOUND_SELECT
  /* If there is are a sequence of queries, do the earlier ones first.
  */
  if( p->pPrior ){
    return multiSelect(pParse, p, eDest, iParm, aff);
  }
#endif

  /* Make local copies of the parameters for this query.
  */
  pTabList = p->pSrc;
  pWhere = p->pWhere;
  pOrderBy = p->pOrderBy;
  pGroupBy = p->pGroupBy;
................................................................................
    rc = 0;
    goto select_end;
  }

  /* Check to see if this is a subquery that can be "flattened" into its parent.
  ** If flattening is a possiblity, do so and return immediately.  
  */
#ifndef SQLITE_OMIT_VIEW
  if( pParent && pParentAgg &&
      flattenSubquery(pParse, pParent, parentTab, *pParentAgg, isAgg) ){
    if( isAgg ) *pParentAgg = 1;
    return rc;
  }
#endif

  /* If there is an ORDER BY clause, resolve any collation sequences
  ** names that have been explicitly specified.
  */
  if( pOrderBy ){
    for(i=0; i<pOrderBy->nExpr; i++){
      if( pOrderBy->a[i].zName ){

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1255
1256
1257
1258
1259
1260
1261


1262
1263




1264
1265
1266
1267
1268
1269
1270
....
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
....
1333
1334
1335
1336
1337
1338
1339


1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354









1355
1356
1357
1358
1359
1360
1361
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.328 2004/10/22 20:29:22 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** These #defines should enable >2GB file support on Posix if the
** underlying operating system supports it.  If the OS lacks
................................................................................
void sqlite3AddColumn(Parse*,Token*);
void sqlite3AddNotNull(Parse*, int);
void sqlite3AddPrimaryKey(Parse*, ExprList*, int);
void sqlite3AddColumnType(Parse*,Token*,Token*);
void sqlite3AddDefaultValue(Parse*,Token*,int);
void sqlite3AddCollateType(Parse*, const char*, int);
void sqlite3EndTable(Parse*,Token*,Select*);


void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int);
int sqlite3ViewGetColumnNames(Parse*,Table*);




void sqlite3DropTable(Parse*, SrcList*, int);
void sqlite3DeleteTable(sqlite3*, Table*);
void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
IdList *sqlite3IdListAppend(IdList*, Token*);
int sqlite3IdListIndex(IdList*,const char*);
SrcList *sqlite3SrcListAppend(SrcList*, Token*, Token*);
void sqlite3SrcListAddAlias(SrcList*, Token*);
................................................................................
void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
Table *sqlite3FindTable(sqlite3*,const char*, const char*);
Table *sqlite3LocateTable(Parse*,const char*, const char*);
Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
void sqlite3Vacuum(Parse*, Token*);
int sqlite3RunVacuum(char**, sqlite3*);
char *sqlite3NameFromToken(Token*);
int sqlite3ExprCheck(Parse*, Expr*, int, int*);
int sqlite3ExprCompare(Expr*, Expr*);
int sqliteFuncId(Token*);
int sqlite3ExprResolveIds(Parse*, SrcList*, ExprList*, Expr*);
................................................................................
FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int);
void sqlite3RegisterBuiltinFunctions(sqlite3*);
void sqlite3RegisterDateTimeFunctions(sqlite3*);
int sqlite3SafetyOn(sqlite3*);
int sqlite3SafetyOff(sqlite3*);
int sqlite3SafetyCheck(sqlite3*);
void sqlite3ChangeCookie(sqlite3*, Vdbe*, int);


void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
                         int,Expr*,int);
void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*);
void sqlite3DropTrigger(Parse*, SrcList*);
void sqlite3DropTriggerPtr(Parse*, Trigger*, int);
int sqlite3TriggersExist(Parse* , Trigger* , int , int , int, ExprList*);
int sqlite3CodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int, 
                         int, int);
void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
void sqlite3DeleteTriggerStep(TriggerStep*);
TriggerStep *sqlite3TriggerSelectStep(Select*);
TriggerStep *sqlite3TriggerInsertStep(Token*, IdList*, ExprList*, Select*, int);
TriggerStep *sqlite3TriggerUpdateStep(Token*, ExprList*, Expr*, int);
TriggerStep *sqlite3TriggerDeleteStep(Token*, Expr*);
void sqlite3DeleteTrigger(Trigger*);









int sqlite3JoinType(Parse*, Token*, Token*, Token*);
void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
void sqlite3DeferForeignKey(Parse*, int);
#ifndef SQLITE_OMIT_AUTHORIZATION
  void sqlite3AuthRead(Parse*,Expr*,SrcList*);
  int sqlite3AuthCheck(Parse*,int, const char*, const char*, const char*);
  void sqlite3AuthContextPush(Parse*, AuthContext*, const char*);







|







 







>
>
|
|
>
>
>
>







 







<







 







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







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
....
1299
1300
1301
1302
1303
1304
1305

1306
1307
1308
1309
1310
1311
1312
....
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.329 2004/10/31 02:22:49 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** These #defines should enable >2GB file support on Posix if the
** underlying operating system supports it.  If the OS lacks
................................................................................
void sqlite3AddColumn(Parse*,Token*);
void sqlite3AddNotNull(Parse*, int);
void sqlite3AddPrimaryKey(Parse*, ExprList*, int);
void sqlite3AddColumnType(Parse*,Token*,Token*);
void sqlite3AddDefaultValue(Parse*,Token*,int);
void sqlite3AddCollateType(Parse*, const char*, int);
void sqlite3EndTable(Parse*,Token*,Select*);

#ifndef SQLITE_OMIT_VIEW
  void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int);
  int sqlite3ViewGetColumnNames(Parse*,Table*);
#else
# define sqlite3ViewGetColumnNames(A,B) 0
#endif

void sqlite3DropTable(Parse*, SrcList*, int);
void sqlite3DeleteTable(sqlite3*, Table*);
void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
IdList *sqlite3IdListAppend(IdList*, Token*);
int sqlite3IdListIndex(IdList*,const char*);
SrcList *sqlite3SrcListAppend(SrcList*, Token*, Token*);
void sqlite3SrcListAddAlias(SrcList*, Token*);
................................................................................
void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
Table *sqlite3FindTable(sqlite3*,const char*, const char*);
Table *sqlite3LocateTable(Parse*,const char*, const char*);
Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);

void sqlite3Vacuum(Parse*, Token*);
int sqlite3RunVacuum(char**, sqlite3*);
char *sqlite3NameFromToken(Token*);
int sqlite3ExprCheck(Parse*, Expr*, int, int*);
int sqlite3ExprCompare(Expr*, Expr*);
int sqliteFuncId(Token*);
int sqlite3ExprResolveIds(Parse*, SrcList*, ExprList*, Expr*);
................................................................................
FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int);
void sqlite3RegisterBuiltinFunctions(sqlite3*);
void sqlite3RegisterDateTimeFunctions(sqlite3*);
int sqlite3SafetyOn(sqlite3*);
int sqlite3SafetyOff(sqlite3*);
int sqlite3SafetyCheck(sqlite3*);
void sqlite3ChangeCookie(sqlite3*, Vdbe*, int);

#ifndef SQLITE_OMIT_TRIGGER
  void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
                           int,Expr*,int);
  void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*);
  void sqlite3DropTrigger(Parse*, SrcList*);
  void sqlite3DropTriggerPtr(Parse*, Trigger*, int);
  int sqlite3TriggersExist(Parse* , Trigger* , int , int , int, ExprList*);
  int sqlite3CodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int, 
                           int, int);
  void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
  void sqlite3DeleteTriggerStep(TriggerStep*);
  TriggerStep *sqlite3TriggerSelectStep(Select*);
  TriggerStep *sqlite3TriggerInsertStep(Token*, IdList*, ExprList*,Select*,int);
  TriggerStep *sqlite3TriggerUpdateStep(Token*, ExprList*, Expr*, int);
  TriggerStep *sqlite3TriggerDeleteStep(Token*, Expr*);
  void sqlite3DeleteTrigger(Trigger*);
  void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
#else
# define sqlite3TriggersExist(A,B,C,D,E,F) 0
# define sqlite3DeleteTrigger(A)
# define sqlite3DropTriggerPtr(A,B,C)
# define sqlite3UnlinkAndDeleteTrigger(A,B,C)
# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I) 0
#endif

int sqlite3JoinType(Parse*, Token*, Token*, Token*);
void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
void sqlite3DeferForeignKey(Parse*, int);
#ifndef SQLITE_OMIT_AUTHORIZATION
  void sqlite3AuthRead(Parse*,Expr*,SrcList*);
  int sqlite3AuthCheck(Parse*,int, const char*, const char*, const char*);
  void sqlite3AuthContextPush(Parse*, AuthContext*, const char*);

Changes to src/test1.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
....
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
....
2524
2525
2526
2527
2528
2529
2530






























2531
2532
2533
2534
2535
2536
2537
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.105 2004/10/30 20:23:09 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

................................................................................
  Tcl_SetVar2(interp, "sqlite_options", "progress", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "progress", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_DATETIME_FUNCS
  Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "datatime", "1", TCL_GLOBAL_ONLY);
#endif
#if defined(THREADSAFE) && THREADSAFE
  Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "0", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_COMPOUND_SELECT
................................................................................
  Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
  Tcl_SetVar2(interp, "sqlite_options", "conflict", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY);
#endif






























}

/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest1_Init(Tcl_Interp *interp){
  extern int sqlite3_search_count;







|







 







|







 







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







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
....
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
....
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.106 2004/10/31 02:22:49 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

................................................................................
  Tcl_SetVar2(interp, "sqlite_options", "progress", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "progress", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_DATETIME_FUNCS
  Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "datetime", "1", TCL_GLOBAL_ONLY);
#endif
#if defined(THREADSAFE) && THREADSAFE
  Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "0", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_COMPOUND_SELECT
................................................................................
  Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
  Tcl_SetVar2(interp, "sqlite_options", "conflict", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_FLOATING_POINT
  Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_MEMORYDB
  Tcl_SetVar2(interp, "sqlite_options", "memorydb", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "memorydb", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_UTF16
  Tcl_SetVar2(interp, "sqlite_options", "utf16", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "utf16", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_EXPLAIN
  Tcl_SetVar2(interp, "sqlite_options", "explain", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "explain", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_TCL_VARIABLE
  Tcl_SetVar2(interp, "sqlite_options", "tclvar", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_BLOB_LITERAL
  Tcl_SetVar2(interp, "sqlite_options", "bloblit", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "bloblit", "1", TCL_GLOBAL_ONLY);
#endif
}

/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest1_Init(Tcl_Interp *interp){
  extern int sqlite3_search_count;

Changes to src/test3.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
574
575
576
577
578
579
580

581



582
583
584
585
586
587
588
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the btree.c module in SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test3.c,v 1.52 2004/09/17 19:39:24 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
#include "btree.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
................................................................................
  }
  pBt = sqlite3TextToPtr(argv[1]);
  nRoot = argc-2;
  aRoot = malloc( sizeof(int)*(argc-2) );
  for(i=0; i<argc-2; i++){
    if( Tcl_GetInt(interp, argv[i+2], &aRoot[i]) ) return TCL_ERROR;
  }

  zResult = sqlite3BtreeIntegrityCheck(pBt, aRoot, nRoot);



  if( zResult ){
    Tcl_AppendResult(interp, zResult, 0);
    sqliteFree(zResult); 
  }
  return TCL_OK;
}








|







 







>

>
>
>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the btree.c module in SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test3.c,v 1.53 2004/10/31 02:22:49 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
#include "btree.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
................................................................................
  }
  pBt = sqlite3TextToPtr(argv[1]);
  nRoot = argc-2;
  aRoot = malloc( sizeof(int)*(argc-2) );
  for(i=0; i<argc-2; i++){
    if( Tcl_GetInt(interp, argv[i+2], &aRoot[i]) ) return TCL_ERROR;
  }
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
  zResult = sqlite3BtreeIntegrityCheck(pBt, aRoot, nRoot);
#else
  zResult = "ok";
#endif
  if( zResult ){
    Tcl_AppendResult(interp, zResult, 0);
    sqliteFree(zResult); 
  }
  return TCL_OK;
}

Changes to src/tokenize.c.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
283
284
285
286
287
288
289

290
291
292
293
294
295
296
...
297
298
299
300
301
302
303

304
305
306
307
308
309
310
...
314
315
316
317
318
319
320

321
322
323
324
325
326
327
...
350
351
352
353
354
355
356
357


358
359
360
361
362
363
364
...
370
371
372
373
374
375
376

377
378
379
380
381
382
383
...
498
499
500
501
502
503
504



505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
...
520
521
522
523
524
525
526



527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548



549
550
551
552
553
554
555
556
557
558




559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578











579
580
581
582
583
584
585
...
631
632
633
634
635
636
637



638
639
640
641
642
643
644
...
655
656
657
658
659
660
661


662
663
664


665
666
667
668
669
670
671
672
673

674
675
676
677
678
679
680
...
681
682
683
684
685
686
687

688
689
690
691
692
693
694
...
700
701
702
703
704
705
706

*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that splits an SQL input string up into
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.92 2004/10/23 05:10:18 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include <stdlib.h>

/*
................................................................................
      *tokenType = TK_DOT;
      return 1;
    }
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9': {
      *tokenType = TK_INTEGER;
      for(i=1; isdigit(z[i]); i++){}

      if( z[i]=='.' && isdigit(z[i+1]) ){
        i += 2;
        while( isdigit(z[i]) ){ i++; }
        *tokenType = TK_FLOAT;
      }
      if( (z[i]=='e' || z[i]=='E') &&
           ( isdigit(z[i+1]) 
................................................................................
            || ((z[i+1]=='+' || z[i+1]=='-') && isdigit(z[i+2]))
           )
      ){
        i += 2;
        while( isdigit(z[i]) ){ i++; }
        *tokenType = TK_FLOAT;
      }

      return i;
    }
    case '[': {
      for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){}
      *tokenType = TK_ID;
      return i;
    }
................................................................................
      return i;
    }
    case ':': {
      for(i=1; IdChar(z[i]); i++){}
      *tokenType = i>1 ? TK_VARIABLE : TK_ILLEGAL;
      return i;
    }

    case '$': {
      *tokenType = TK_VARIABLE;
      if( z[1]=='{' ){
        int nBrace = 1;
        for(i=2; (c=z[i])!=0 && nBrace; i++){
          if( c=='{' ){
            nBrace++;
................................................................................
          }else{
            break;
          }
        }
        if( n==0 ) *tokenType = TK_ILLEGAL;
      }
      return i;
    } 


    case 'x': case 'X': {
      if( (c=z[1])=='\'' || c=='"' ){
        int delim = c;
        *tokenType = TK_BLOB;
        for(i=2; (c=z[i])!=0; i++){
          if( c==delim ){
            if( i%2 ) *tokenType = TK_ILLEGAL;
................................................................................
          }
        }
        if( c ) i++;
        return i;
      }
      /* Otherwise fall through to the next case */
    }

    default: {
      if( !IdChar(*z) ){
        break;
      }
      for(i=1; IdChar(z[i]); i++){}
      *tokenType = sqlite3KeywordCode((char*)z, i);
      return i;
................................................................................
  return nErr;
}

/*
** Token types used by the sqlite3_complete() routine.  See the header
** comments on that procedure for additional information.
*/



#define tkEXPLAIN 0
#define tkCREATE  1
#define tkTEMP    2
#define tkTRIGGER 3
#define tkEND     4
#define tkSEMI    5
#define tkWS      6
#define tkOTHER   7

/*
** Return TRUE if the given SQL string ends in a semicolon.
**
** Special handling is require for CREATE TRIGGER statements.
** Whenever the CREATE TRIGGER keywords are seen, the statement
** must end with ";END;".
................................................................................
**
** This implementation uses a state machine with 7 states:
**
**   (0) START     At the beginning or end of an SQL statement.  This routine
**                 returns 1 if it ends in the START state and 0 if it ends
**                 in any other state.
**



**   (1) EXPLAIN   The keyword EXPLAIN has been seen at the beginning of 
**                 a statement.
**
**   (2) CREATE    The keyword CREATE has been seen at the beginning of a
**                 statement, possibly preceeded by EXPLAIN and/or followed by
**                 TEMP or TEMPORARY
**
**   (3) NORMAL    We are in the middle of statement which ends with a single
**                 semicolon.
**
**   (4) TRIGGER   We are in the middle of a trigger definition that must be
**                 ended by a semicolon, the keyword END, and another semicolon.
**
**   (5) SEMI      We've seen the first semicolon in the ";END;" that occurs at
**                 the end of a trigger definition.
**
**   (6) END       We've seen the ";END" of the ";END;" that occurs at the end
**                 of a trigger difinition.
**
** Transitions between states above are determined by tokens extracted
** from the input.  The following tokens are significant:
**



**   (0) tkEXPLAIN   The "explain" keyword.
**   (1) tkCREATE    The "create" keyword.
**   (2) tkTEMP      The "temp" or "temporary" keyword.
**   (3) tkTRIGGER   The "trigger" keyword.
**   (4) tkEND       The "end" keyword.
**   (5) tkSEMI      A semicolon.
**   (6) tkWS        Whitespace
**   (7) tkOTHER     Any other SQL token.
**
** Whitespace never causes a state transition and is always ignored.




*/
int sqlite3_complete(const char *zSql){
  u8 state = 0;   /* Current state, using numbers defined in header comment */
  u8 token;       /* Value of the next token */

  /* The following matrix defines the transition from one state to another
  ** according to what token is seen.  trans[state][token] returns the
  ** next state.
  */
  static const u8 trans[7][8] = {
                     /* Token:                                                */
     /* State:       **  EXPLAIN  CREATE  TEMP  TRIGGER  END  SEMI  WS  OTHER */
     /* 0   START: */ {       1,      2,    3,       3,   3,    0,  0,     3, },
     /* 1 EXPLAIN: */ {       3,      2,    3,       3,   3,    0,  1,     3, },
     /* 2  CREATE: */ {       3,      3,    2,       4,   3,    0,  2,     3, },
     /* 3  NORMAL: */ {       3,      3,    3,       3,   3,    0,  3,     3, },
     /* 4 TRIGGER: */ {       4,      4,    4,       4,   4,    5,  4,     4, },
     /* 5    SEMI: */ {       4,      4,    4,       4,   6,    5,  5,     4, },
     /* 6     END: */ {       4,      4,    4,       4,   4,    0,  6,     4, },
  };












  while( *zSql ){
    switch( *zSql ){
      case ';': {  /* A semicolon */
        token = tkSEMI;
        break;
      }
................................................................................
      }
      default: {
        int c;
        if( IdChar((u8)*zSql) ){
          /* Keywords and unquoted identifiers */
          int nId;
          for(nId=1; IdChar(zSql[nId]); nId++){}



          switch( *zSql ){
            case 'c': case 'C': {
              if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){
                token = tkCREATE;
              }else{
                token = tkOTHER;
              }
................................................................................
                token = tkOTHER;
              }
              break;
            }
            case 'e':  case 'E': {
              if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){
                token = tkEND;


              }else if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){
                token = tkEXPLAIN;
              }else{


                token = tkOTHER;
              }
              break;
            }
            default: {
              token = tkOTHER;
              break;
            }
          }

          zSql += nId-1;
        }else{
          /* Operators and special symbols */
          token = tkOTHER;
        }
        break;
      }
................................................................................
    }
    state = trans[state][token];
    zSql++;
  }
  return state==0;
}


/*
** This routine is the same as the sqlite3_complete() routine described
** above, except that the parameter is required to be UTF-16 encoded, not
** UTF-8.
*/
int sqlite3_complete16(const void *zSql){
  sqlite3_value *pVal;
................................................................................
  zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8);
  if( zSql8 ){
    rc = sqlite3_complete(zSql8);
  }
  sqlite3ValueFree(pVal);
  return rc;
}








|







 







>







 







>







 







>







 







|
>
>







 







>







 







>
>
>
|
|
|
|
|
<
<
<







 







>
>
>
|


|



<
<
<












>
>
>
|
|
|
|
|
<
<
<


>
>
>
>





|
|
|



|
|
|
|
|
|
|
|

>
>
>
>
>
>
>
>
>
>
>







 







>
>
>







 







>
>
|

|
>
>









>







 







>







 







>
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
...
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
...
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
...
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
...
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
...
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518



519
520
521
522
523
524
525
...
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542



543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562



563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
...
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
...
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
...
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
...
730
731
732
733
734
735
736
737
*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that splits an SQL input string up into
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.93 2004/10/31 02:22:49 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include <stdlib.h>

/*
................................................................................
      *tokenType = TK_DOT;
      return 1;
    }
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9': {
      *tokenType = TK_INTEGER;
      for(i=1; isdigit(z[i]); i++){}
#ifndef SQLITE_OMIT_FLOATING_POINT
      if( z[i]=='.' && isdigit(z[i+1]) ){
        i += 2;
        while( isdigit(z[i]) ){ i++; }
        *tokenType = TK_FLOAT;
      }
      if( (z[i]=='e' || z[i]=='E') &&
           ( isdigit(z[i+1]) 
................................................................................
            || ((z[i+1]=='+' || z[i+1]=='-') && isdigit(z[i+2]))
           )
      ){
        i += 2;
        while( isdigit(z[i]) ){ i++; }
        *tokenType = TK_FLOAT;
      }
#endif
      return i;
    }
    case '[': {
      for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){}
      *tokenType = TK_ID;
      return i;
    }
................................................................................
      return i;
    }
    case ':': {
      for(i=1; IdChar(z[i]); i++){}
      *tokenType = i>1 ? TK_VARIABLE : TK_ILLEGAL;
      return i;
    }
#ifndef SQLITE_OMIT_TCL_VARIABLE
    case '$': {
      *tokenType = TK_VARIABLE;
      if( z[1]=='{' ){
        int nBrace = 1;
        for(i=2; (c=z[i])!=0 && nBrace; i++){
          if( c=='{' ){
            nBrace++;
................................................................................
          }else{
            break;
          }
        }
        if( n==0 ) *tokenType = TK_ILLEGAL;
      }
      return i;
    }
#endif
#ifndef SQLITE_OMIT_BLOB_LITERAL
    case 'x': case 'X': {
      if( (c=z[1])=='\'' || c=='"' ){
        int delim = c;
        *tokenType = TK_BLOB;
        for(i=2; (c=z[i])!=0; i++){
          if( c==delim ){
            if( i%2 ) *tokenType = TK_ILLEGAL;
................................................................................
          }
        }
        if( c ) i++;
        return i;
      }
      /* Otherwise fall through to the next case */
    }
#endif
    default: {
      if( !IdChar(*z) ){
        break;
      }
      for(i=1; IdChar(z[i]); i++){}
      *tokenType = sqlite3KeywordCode((char*)z, i);
      return i;
................................................................................
  return nErr;
}

/*
** Token types used by the sqlite3_complete() routine.  See the header
** comments on that procedure for additional information.
*/
#define tkSEMI    0
#define tkWS      1
#define tkOTHER   2
#define tkEXPLAIN 3
#define tkCREATE  4
#define tkTEMP    5
#define tkTRIGGER 6
#define tkEND     7




/*
** Return TRUE if the given SQL string ends in a semicolon.
**
** Special handling is require for CREATE TRIGGER statements.
** Whenever the CREATE TRIGGER keywords are seen, the statement
** must end with ";END;".
................................................................................
**
** This implementation uses a state machine with 7 states:
**
**   (0) START     At the beginning or end of an SQL statement.  This routine
**                 returns 1 if it ends in the START state and 0 if it ends
**                 in any other state.
**
**   (1) NORMAL    We are in the middle of statement which ends with a single
**                 semicolon.
**
**   (2) EXPLAIN   The keyword EXPLAIN has been seen at the beginning of 
**                 a statement.
**
**   (3) CREATE    The keyword CREATE has been seen at the beginning of a
**                 statement, possibly preceeded by EXPLAIN and/or followed by
**                 TEMP or TEMPORARY
**



**   (4) TRIGGER   We are in the middle of a trigger definition that must be
**                 ended by a semicolon, the keyword END, and another semicolon.
**
**   (5) SEMI      We've seen the first semicolon in the ";END;" that occurs at
**                 the end of a trigger definition.
**
**   (6) END       We've seen the ";END" of the ";END;" that occurs at the end
**                 of a trigger difinition.
**
** Transitions between states above are determined by tokens extracted
** from the input.  The following tokens are significant:
**
**   (0) tkSEMI      A semicolon.
**   (1) tkWS        Whitespace
**   (2) tkOTHER     Any other SQL token.
**   (3) tkEXPLAIN   The "explain" keyword.
**   (4) tkCREATE    The "create" keyword.
**   (5) tkTEMP      The "temp" or "temporary" keyword.
**   (6) tkTRIGGER   The "trigger" keyword.
**   (7) tkEND       The "end" keyword.



**
** Whitespace never causes a state transition and is always ignored.
**
** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed
** to recognize the end of a trigger can be omitted.  All we have to do
** is look for a semicolon that is not part of an string or comment.
*/
int sqlite3_complete(const char *zSql){
  u8 state = 0;   /* Current state, using numbers defined in header comment */
  u8 token;       /* Value of the next token */

#ifndef SQLITE_OMIT_TRIGGER
  /* A complex statement machine used to detect the end of a CREATE TRIGGER
  ** statement.  This is the normal case.
  */
  static const u8 trans[7][8] = {
                     /* Token:                                                */
     /* State:       **  SEMI  WS  OTHER EXPLAIN  CREATE  TEMP  TRIGGER  END  */
     /* 0   START: */ {    0,  0,     1,      2,      3,    1,       1,   1,  },
     /* 1  NORMAL: */ {    0,  1,     1,      1,      1,    1,       1,   1,  },
     /* 2 EXPLAIN: */ {    0,  2,     1,      1,      3,    1,       1,   1,  },
     /* 3  CREATE: */ {    0,  3,     1,      1,      1,    3,       4,   1,  },
     /* 4 TRIGGER: */ {    5,  4,     4,      4,      4,    4,       4,   4,  },
     /* 5    SEMI: */ {    5,  5,     4,      4,      4,    4,       4,   6,  },
     /* 6     END: */ {    0,  6,     4,      4,      4,    4,       4,   4,  },
  };
#else
  /* If triggers are not suppored by this compile then the statement machine
  ** used to detect the end of a statement is much simplier
  */
  static const u8 trans[2][3] = {
                     /* Token:           */
     /* State:       **  SEMI  WS  OTHER */
     /* 0   START: */ {    0,  0,     1, },
     /* 1  NORMAL: */ {    0,  1,     1, },
  };
#endif /* SQLITE_OMIT_TRIGGER */

  while( *zSql ){
    switch( *zSql ){
      case ';': {  /* A semicolon */
        token = tkSEMI;
        break;
      }
................................................................................
      }
      default: {
        int c;
        if( IdChar((u8)*zSql) ){
          /* Keywords and unquoted identifiers */
          int nId;
          for(nId=1; IdChar(zSql[nId]); nId++){}
#ifdef SQLITE_OMIT_TRIGGER
          token = tkOTHER;
#else
          switch( *zSql ){
            case 'c': case 'C': {
              if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){
                token = tkCREATE;
              }else{
                token = tkOTHER;
              }
................................................................................
                token = tkOTHER;
              }
              break;
            }
            case 'e':  case 'E': {
              if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){
                token = tkEND;
              }else
#ifndef SQLITE_OMIT_EXPLAIN
              if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){
                token = tkEXPLAIN;
              }else
#endif
              {
                token = tkOTHER;
              }
              break;
            }
            default: {
              token = tkOTHER;
              break;
            }
          }
#endif /* SQLITE_OMIT_TRIGGER */
          zSql += nId-1;
        }else{
          /* Operators and special symbols */
          token = tkOTHER;
        }
        break;
      }
................................................................................
    }
    state = trans[state][token];
    zSql++;
  }
  return state==0;
}

#ifndef SQLITE_OMIT_UTF16
/*
** This routine is the same as the sqlite3_complete() routine described
** above, except that the parameter is required to be UTF-16 encoded, not
** UTF-8.
*/
int sqlite3_complete16(const void *zSql){
  sqlite3_value *pVal;
................................................................................
  zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8);
  if( zSql8 ){
    rc = sqlite3_complete(zSql8);
  }
  sqlite3ValueFree(pVal);
  return rc;
}
#endif /* SQLITE_OMIT_UTF16 */

Changes to src/trigger.c.

8
9
10
11
12
13
14

15
16
17
18
19
20
21
...
798
799
800
801
802
803
804

**    May you share freely, never taking more than you give.
**
*************************************************************************
*
*/
#include "sqliteInt.h"


/*
** Delete a linked list of TriggerStep structures.
*/
void sqlite3DeleteTriggerStep(TriggerStep *pTriggerStep){
  while( pTriggerStep ){
    TriggerStep * pTmp = pTriggerStep;
    pTriggerStep = pTriggerStep->pNext;
................................................................................

      sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger);
    }
    pTrigger = pTrigger->pNext;
  }
  return 0;
}








>







 







>
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
799
800
801
802
803
804
805
806
**    May you share freely, never taking more than you give.
**
*************************************************************************
*
*/
#include "sqliteInt.h"

#ifndef SQLITE_OMIT_TRIGGER
/*
** Delete a linked list of TriggerStep structures.
*/
void sqlite3DeleteTriggerStep(TriggerStep *pTriggerStep){
  while( pTriggerStep ){
    TriggerStep * pTmp = pTriggerStep;
    pTriggerStep = pTriggerStep->pNext;
................................................................................

      sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger);
    }
    pTrigger = pTrigger->pNext;
  }
  return 0;
}
#endif /* !defined(SQLITE_OMIT_TRIGGER) */

Changes to src/update.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
63
64
65
66
67
68
69





70
71
72
73
74
75











76
77
78
79
80
81
82
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.90 2004/10/05 02:41:43 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
**
**   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
................................................................................
  db = pParse->db;
  assert( pTabList->nSrc==1 );

  /* Locate the table which we want to update. 
  */
  pTab = sqlite3SrcListLookup(pParse, pTabList);
  if( pTab==0 ) goto update_cleanup;





  before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, 
            TK_UPDATE, TK_BEFORE, TK_ROW, pChanges);
  after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, 
            TK_UPDATE, TK_AFTER, TK_ROW, pChanges);
  row_triggers_exist = before_triggers || after_triggers;
  isView = pTab->pSelect!=0;











  if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){
    goto update_cleanup;
  }
  if( isView ){
    if( sqlite3ViewGetColumnNames(pParse, pTab) ){
      goto update_cleanup;
    }







|







 







>
>
>
>
>

|

|


>
>
>
>
>
>
>
>
>
>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
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
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.91 2004/10/31 02:22:49 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
**
**   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
................................................................................
  db = pParse->db;
  assert( pTabList->nSrc==1 );

  /* Locate the table which we want to update. 
  */
  pTab = sqlite3SrcListLookup(pParse, pTabList);
  if( pTab==0 ) goto update_cleanup;

  /* Figure out if we have any triggers and if the table being
  ** updated is a view
  */
#ifndef SQLITE_OMIT_TRIGGER
  before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, 
                         TK_UPDATE, TK_BEFORE, TK_ROW, pChanges);
  after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, 
                         TK_UPDATE, TK_AFTER, TK_ROW, pChanges);
  row_triggers_exist = before_triggers || after_triggers;
  isView = pTab->pSelect!=0;
#else
# define before_triggers 0
# define after_triggers 0
# define row_triggers_exist 0
# define isView 0
#endif
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif

  if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){
    goto update_cleanup;
  }
  if( isView ){
    if( sqlite3ViewGetColumnNames(pParse, pTab) ){
      goto update_cleanup;
    }

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
3731
3732
3733
3734
3735
3736
3737

3738
3739
3740
3741
3742
3743
3744
....
3782
3783
3784
3785
3786
3787
3788

3789
3790
3791
3792
3793
3794
3795
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.419 2004/10/19 16:40:59 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
*/
case OP_DropTrigger: {
  sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p3);
  break;
}



/* Opcode: IntegrityCk * P2 *
**
** Do an analysis of the currently open database.  Push onto the
** stack the text of an error message describing any problems.
** If there are no errors, push a "ok" onto the stack.
**
** The root page numbers of all tables in the database are integer
................................................................................
    pTos->xDel = 0;
  }
  pTos->enc = SQLITE_UTF8;
  sqlite3VdbeChangeEncoding(pTos, db->enc);
  sqliteFree(aRoot);
  break;
}


/* Opcode: ListWrite * * *
**
** Write the integer on the top of the stack
** into the temporary storage list.
*/
case OP_ListWrite: {







|







 







>







 







>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
....
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.420 2004/10/31 02:22:50 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
*/
case OP_DropTrigger: {
  sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p3);
  break;
}


#ifndef SQLITE_OMIT_INTEGRITY_CHECK
/* Opcode: IntegrityCk * P2 *
**
** Do an analysis of the currently open database.  Push onto the
** stack the text of an error message describing any problems.
** If there are no errors, push a "ok" onto the stack.
**
** The root page numbers of all tables in the database are integer
................................................................................
    pTos->xDel = 0;
  }
  pTos->enc = SQLITE_UTF8;
  sqlite3VdbeChangeEncoding(pTos, db->enc);
  sqliteFree(aRoot);
  break;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

/* Opcode: ListWrite * * *
**
** Write the integer on the top of the stack
** into the temporary storage list.
*/
case OP_ListWrite: {

Changes to src/vdbeapi.c.

173
174
175
176
177
178
179

180
181
182


183
184
185
186
187
188
189
      sqlite3DebugPrintf("SQL-trace: %s\n", p->aOp[p->nOp-1].p3);
    }
#endif /* SQLITE_DEBUG */

    db->activeVdbeCnt++;
    p->pc = 0;
  }

  if( p->explain ){
    rc = sqlite3VdbeList(p);
  }else{


    rc = sqlite3VdbeExec(p);
  }

  if( sqlite3SafetyOff(db) ){
    rc = SQLITE_MISUSE;
  }








>


|
>
>







173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
      sqlite3DebugPrintf("SQL-trace: %s\n", p->aOp[p->nOp-1].p3);
    }
#endif /* SQLITE_DEBUG */

    db->activeVdbeCnt++;
    p->pc = 0;
  }
#ifndef SQLITE_OMIT_EXPLAIN
  if( p->explain ){
    rc = sqlite3VdbeList(p);
  }else
#endif /* SQLITE_OMIT_EXPLAIN */
  {
    rc = sqlite3VdbeExec(p);
  }

  if( sqlite3SafetyOff(db) ){
    rc = SQLITE_MISUSE;
  }

Changes to src/vdbeaux.c.

371
372
373
374
375
376
377


378
379
380
381
382
383
384
...
440
441
442
443
444
445
446

447
448
449
450
451
452
453
...
469
470
471
472
473
474
475

476
477
478
479
480
481
482
...
545
546
547
548
549
550
551

552
553
554
555
556
557
558
*/
VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
  assert( p->magic==VDBE_MAGIC_INIT );
  assert( addr>=0 && addr<p->nOp );
  return &p->aOp[addr];
}



/*
** Compute a string that describes the P3 parameter for an opcode.
** Use zTemp for any required temporary buffer space.
*/
static char *displayP3(Op *pOp, char *zTemp, int nTemp){
  char *zP3;
  assert( nTemp>=20 );
................................................................................
      if( zP3==0 || pOp->opcode==OP_Noop ){
        zP3 = "";
      }
    }
  }
  return zP3;
}



#if !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
/*
** Print a single opcode.  This routine is used for debugging only.
*/
void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
................................................................................
  if( p ){
    while( N-->0 ){
      sqlite3VdbeMemRelease(p++);
    }
  }
}


/*
** Give a listing of the program in the virtual machine.
**
** The interface is the same as sqlite3VdbeExec().  But instead of
** running the code, it invokes the callback once for each instruction.
** This feature is used to implement "EXPLAIN".
*/
................................................................................
    p->pTos = pMem;
    p->rc = SQLITE_OK;
    p->resOnStack = 1;
    rc = SQLITE_ROW;
  }
  return rc;
}


/*
** Print the SQL that was used to generate a VDBE program.
*/
void sqlite3VdbePrintSql(Vdbe *p){
#ifdef SQLITE_DEBUG
  int nOp = p->nOp;







>
>







 







>







 







>







 







>







371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
...
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
...
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
...
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
*/
VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
  assert( p->magic==VDBE_MAGIC_INIT );
  assert( addr>=0 && addr<p->nOp );
  return &p->aOp[addr];
}

#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
     || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
/*
** Compute a string that describes the P3 parameter for an opcode.
** Use zTemp for any required temporary buffer space.
*/
static char *displayP3(Op *pOp, char *zTemp, int nTemp){
  char *zP3;
  assert( nTemp>=20 );
................................................................................
      if( zP3==0 || pOp->opcode==OP_Noop ){
        zP3 = "";
      }
    }
  }
  return zP3;
}
#endif


#if !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
/*
** Print a single opcode.  This routine is used for debugging only.
*/
void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
................................................................................
  if( p ){
    while( N-->0 ){
      sqlite3VdbeMemRelease(p++);
    }
  }
}

#ifndef SQLITE_OMIT_EXPLAIN
/*
** Give a listing of the program in the virtual machine.
**
** The interface is the same as sqlite3VdbeExec().  But instead of
** running the code, it invokes the callback once for each instruction.
** This feature is used to implement "EXPLAIN".
*/
................................................................................
    p->pTos = pMem;
    p->rc = SQLITE_OK;
    p->resOnStack = 1;
    rc = SQLITE_ROW;
  }
  return rc;
}
#endif /* SQLITE_OMIT_EXPLAIN */

/*
** Print the SQL that was used to generate a VDBE program.
*/
void sqlite3VdbePrintSql(Vdbe *p){
#ifdef SQLITE_DEBUG
  int nOp = p->nOp;

Changes to test/attach.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
201
202
203
204
205
206
207

208
209
210
211
212
213
214
...
288
289
290
291
292
293
294

295
296
297
298
299
300
301
302
303
304


















305
306
307
308
309
310
311
...
430
431
432
433
434
435
436

437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459

460
461
462
463
464
465
466
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: attach.test,v 1.26 2004/08/18 15:58:24 drh Exp $
#

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

for {set i 2} {$i<=15} {incr i} {
  file delete -force test$i.db
................................................................................
    DETACH db2;
  }
} {0 {}}
do_test attach-1.29 {
  db_list db
} {0 main 1 temp}


do_test attach-2.1 {
  execsql {
    CREATE TABLE tx(x1,x2,y1,y2);
    CREATE TRIGGER r1 AFTER UPDATE ON t2 FOR EACH ROW BEGIN
      INSERT INTO tx(x1,x2,y1,y2) VALUES(OLD.x,NEW.x,OLD.y,NEW.y);
    END;
    SELECT * FROM tx;
................................................................................
  db close
  sqlite3 db test.db
  execsql {
    ATTACH 'test2.db' AS db2;
    SELECT type, name, tbl_name FROM db2.sqlite_master;
  }
} {table t2 t2 table tx tx trigger r1 t2 index i2 t2}


do_test attach-3.1 {
  db close
  db2 close
  sqlite3 db test.db
  sqlite3 db2 test2.db
  execsql {
    SELECT * FROM t1
  }
} {1 2 3 4}


















do_test attach-3.2 {
  catchsql {
    SELECT * FROM t2
  }
} {1 {no such table: t2}}
do_test attach-3.3 {
  catchsql {
................................................................................
} {9 10}
do_test attach-4.5 {
  execsql {
    INSERT INTO db2.t3 VALUES(9,10);
    SELECT * FROM db2.t3;
  }
} {1 2 9 10}

do_test attach-4.6 {
  execsql {
    DETACH db2;
  }
  execsql {
    CREATE TABLE t4(x);
    CREATE TRIGGER t3r3 AFTER INSERT ON t3 BEGIN
      INSERT INTO t4 VALUES('db2.' || NEW.x);
    END;
    INSERT INTO t3 VALUES(6,7);
    SELECT * FROM t4;
  } db2
} {db2.6}
do_test attach-4.7 {
  execsql {
    CREATE TABLE t4(y);
    CREATE TRIGGER t3r3 AFTER INSERT ON t3 BEGIN
      INSERT INTO t4 VALUES('main.' || NEW.a);
    END;
    INSERT INTO main.t3 VALUES(11,12);
    SELECT * FROM main.t4;
  }
} {main.11}


# This one is tricky.  On the UNION ALL select, we have to make sure
# the schema for both main and db2 is valid before starting to execute
# the first query of the UNION ALL.  If we wait to test the validity of
# the schema for main until after the first query has run, that test will
# fail and the query will abort but we will have already output some
# results.  When the query is retried, the results will be repeated.







|







 







>







 







>










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







 







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







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
...
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
...
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: attach.test,v 1.27 2004/10/31 02:22:50 drh Exp $
#

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

for {set i 2} {$i<=15} {incr i} {
  file delete -force test$i.db
................................................................................
    DETACH db2;
  }
} {0 {}}
do_test attach-1.29 {
  db_list db
} {0 main 1 temp}

ifcapable {trigger} {  # Only do the following tests if triggers are enabled
do_test attach-2.1 {
  execsql {
    CREATE TABLE tx(x1,x2,y1,y2);
    CREATE TRIGGER r1 AFTER UPDATE ON t2 FOR EACH ROW BEGIN
      INSERT INTO tx(x1,x2,y1,y2) VALUES(OLD.x,NEW.x,OLD.y,NEW.y);
    END;
    SELECT * FROM tx;
................................................................................
  db close
  sqlite3 db test.db
  execsql {
    ATTACH 'test2.db' AS db2;
    SELECT type, name, tbl_name FROM db2.sqlite_master;
  }
} {table t2 t2 table tx tx trigger r1 t2 index i2 t2}
} ;# End of ifcapable {trigger}

do_test attach-3.1 {
  db close
  db2 close
  sqlite3 db test.db
  sqlite3 db2 test2.db
  execsql {
    SELECT * FROM t1
  }
} {1 2 3 4}

# If we are testing a version of the code that lacks trigger support,
# adjust the database contents so that they are the same if triggers
# had been enabled.
ifcapable {!trigger} {
  db2 eval {
    DELETE FROM t2;
    INSERT INTO t2 VALUES(21, 'x');
    INSERT INTO t2 VALUES(22, 'y');
    CREATE TABLE tx(x1,x2,y1,y2);
    INSERT INTO tx VALUES(1, 11, 'x', 'x');
    INSERT INTO tx VALUES(2, 12, 'y', 'y');
    INSERT INTO tx VALUES(11, 21, 'x', 'x');
    INSERT INTO tx VALUES(12, 22, 'y', 'y');
    CREATE INDEX i2 ON t2(x);
  }
}

do_test attach-3.2 {
  catchsql {
    SELECT * FROM t2
  }
} {1 {no such table: t2}}
do_test attach-3.3 {
  catchsql {
................................................................................
} {9 10}
do_test attach-4.5 {
  execsql {
    INSERT INTO db2.t3 VALUES(9,10);
    SELECT * FROM db2.t3;
  }
} {1 2 9 10}
ifcapable {trigger} {
  do_test attach-4.6 {
    execsql {
      DETACH db2;
    }
    execsql {
      CREATE TABLE t4(x);
      CREATE TRIGGER t3r3 AFTER INSERT ON t3 BEGIN
        INSERT INTO t4 VALUES('db2.' || NEW.x);
      END;
      INSERT INTO t3 VALUES(6,7);
      SELECT * FROM t4;
    } db2
  } {db2.6}
  do_test attach-4.7 {
    execsql {
      CREATE TABLE t4(y);
      CREATE TRIGGER t3r3 AFTER INSERT ON t3 BEGIN
        INSERT INTO t4 VALUES('main.' || NEW.a);
      END;
      INSERT INTO main.t3 VALUES(11,12);
      SELECT * FROM main.t4;
    }
  } {main.11}
}

# This one is tricky.  On the UNION ALL select, we have to make sure
# the schema for both main and db2 is valid before starting to execute
# the first query of the UNION ALL.  If we wait to test the validity of
# the schema for main until after the first query has run, that test will
# fail and the query will abort but we will have already output some
# results.  When the query is retried, the results will be repeated.

Changes to test/date.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing date and time functions.
#
# $Id: date.test,v 1.10 2004/10/30 20:23:10 drh Exp $

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

# Skip this whole file if date and time functions are omitted
# at compile-time
#
if {!$sqlite_options(datetime)} {
  finish_test
  return
}

proc datetest {tnum expr result} {
  do_test date-$tnum [subst {
    execsql "SELECT coalesce($expr,'NULL')"







|







|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing date and time functions.
#
# $Id: date.test,v 1.11 2004/10/31 02:22:50 drh Exp $

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

# Skip this whole file if date and time functions are omitted
# at compile-time
#
ifcapable {!datetime} {
  finish_test
  return
}

proc datetest {tnum expr result} {
  do_test date-$tnum [subst {
    execsql "SELECT coalesce($expr,'NULL')"

Changes to test/trigger1.test.

25
26
27
28
29
30
31



32

33
34
35
36
37
38
39
40
# trig-1.12: Ensure that INSTEAD OF triggers cannot be created on tables
# trig-1.13: Ensure that AFTER triggers cannot be created on views
# trig-1.14: Ensure that BEFORE triggers cannot be created on views
#

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





do_test trigger1-1.1.2 {
   catchsql {
     CREATE TRIGGER trig UPDATE ON no_such_table BEGIN
       SELECT * from sqlite_master;
     END;
   } 
} {1 {no such table: main.no_such_table}}
do_test trigger1-1.1.2 {







>
>
>
|
>
|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# trig-1.12: Ensure that INSTEAD OF triggers cannot be created on tables
# trig-1.13: Ensure that AFTER triggers cannot be created on views
# trig-1.14: Ensure that BEFORE triggers cannot be created on views
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable {!trigger} {
  finish_test
  return
}

do_test trigger1-1.1.1 {
   catchsql {
     CREATE TRIGGER trig UPDATE ON no_such_table BEGIN
       SELECT * from sqlite_master;
     END;
   } 
} {1 {no such table: main.no_such_table}}
do_test trigger1-1.1.2 {

Changes to test/trigger2.test.

45
46
47
48
49
50
51




52
53
54
55
56
57
58
# trigger2-6.2[a-f]: UPDATE statements
#
# 7. Triggers on views fire correctly.
#

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





# 1.
set ii 0
foreach tbl_defn {
	{CREATE TEMP TABLE tbl (a, b);} 
	{CREATE TABLE tbl (a, b);} 
	{CREATE TABLE tbl (a INTEGER PRIMARY KEY, b);} 







>
>
>
>







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# trigger2-6.2[a-f]: UPDATE statements
#
# 7. Triggers on views fire correctly.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable {!trigger} {
  finish_test
  return
}

# 1.
set ii 0
foreach tbl_defn {
	{CREATE TEMP TABLE tbl (a, b);} 
	{CREATE TABLE tbl (a, b);} 
	{CREATE TABLE tbl (a INTEGER PRIMARY KEY, b);} 

Changes to test/trigger3.test.

9
10
11
12
13
14
15




16
17
18
19
20
21
22
#
# This file tests the RAISE() function.
#


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





# Test that we can cause ROLLBACK, FAIL and ABORT correctly
# catchsql { DROP TABLE tbl; }
catchsql { CREATE TABLE tbl (a, b, c) }

execsql {
    CREATE TRIGGER before_tbl_insert BEFORE INSERT ON tbl BEGIN SELECT CASE 







>
>
>
>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#
# This file tests the RAISE() function.
#


set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable {!trigger} {
  finish_test
  return
}

# Test that we can cause ROLLBACK, FAIL and ABORT correctly
# catchsql { DROP TABLE tbl; }
catchsql { CREATE TABLE tbl (a, b, c) }

execsql {
    CREATE TRIGGER before_tbl_insert BEFORE INSERT ON tbl BEGIN SELECT CASE 

Changes to test/trigger4.test.

8
9
10
11
12
13
14




15
16
17
18
19
20
21
#***********************************************************************
#
# This file tests the triggers of views.
#

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





do_test trigger4-1.1 {
  execsql {
    create table test1(id integer primary key,a);
    create table test2(id integer,b);
    create view test as
      select test1.id as id,a as a,b as b







>
>
>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#***********************************************************************
#
# This file tests the triggers of views.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable {!trigger} {
  finish_test
  return
}

do_test trigger4-1.1 {
  execsql {
    create table test1(id integer primary key,a);
    create table test2(id integer,b);
    create view test as
      select test1.id as id,a as a,b as b

Changes to test/trigger5.test.

8
9
10
11
12
13
14




15
16
17
18
19
20
21
#***********************************************************************
#
# This file tests the triggers of views.
#

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





# Ticket #844
#
do_test trigger5-1.1 {
  execsql {
    CREATE TABLE Item(
       a integer PRIMARY KEY NOT NULL ,







>
>
>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#***********************************************************************
#
# This file tests the triggers of views.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable {!trigger} {
  finish_test
  return
}

# Ticket #844
#
do_test trigger5-1.1 {
  execsql {
    CREATE TABLE Item(
       a integer PRIMARY KEY NOT NULL ,