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 |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
be661acfa849bb0d5692797dd221f5a8 |
User & Date: | drh 2004-10-31 02:22:48.000 |
Context
2004-10-31
| ||
16:25 | Add code to create/update the btree 'pointer-map' for auto-vacuum mode. (CVS 2035) (check-in: bebd967f36 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: be661acfa8 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: 2aa506ccb0 user: drh tags: trunk) | |
Changes
Changes to mkopcodec.awk.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #!/usr/bin/awk -f # # This AWK script scans the opcodes.h file (which is itself generated by # another awk script) and uses the information gleaned to create the # opcodes.c source file. # # 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 "};" } | > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #!/usr/bin/awk -f # # This AWK script scans the opcodes.h file (which is itself generated by # another awk script) and uses the information gleaned to create the # opcodes.c source file. # # 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.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2004 April 6 ** ** The author disclaims copyright to this source code. In place of ** 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. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 2004 April 6 ** ** The author disclaims copyright to this source code. In place of ** 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. |
︙ | ︙ | |||
4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 | 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, | > | 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 | 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, |
︙ | ︙ | |||
4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 | 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. */ static int checkRef(IntegrityCk *pCheck, int iPage, char *zContext){ if( iPage==0 ) return 1; if( iPage>pCheck->nPage || iPage<0 ){ checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage); return 1; } 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 */ | > > > > | 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 | 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. */ static int checkRef(IntegrityCk *pCheck, int iPage, char *zContext){ if( iPage==0 ) return 1; if( iPage>pCheck->nPage || iPage<0 ){ checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage); return 1; } 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 */ |
︙ | ︙ | |||
4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 | 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: ** | > > | 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 | 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: ** |
︙ | ︙ | |||
4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 | } } 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() | > > | 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 | } } 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() |
︙ | ︙ | |||
4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 | } /* 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); | > | 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 | } /* 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); |
︙ | ︙ | |||
4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 | ** 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. */ | > | 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 | ** 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. */ |
︙ | ︙ | |||
4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 | 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)); } | > | 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 | 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 | ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ** 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 |
︙ | ︙ | |||
1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 | } 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 */ | > | 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 | } 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 */ |
︙ | ︙ | |||
1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 | 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; | > > | 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 | 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; |
︙ | ︙ | |||
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 | 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; | > > > > > | 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 | 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; |
︙ | ︙ | |||
1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 | 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; | > > < | 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 | 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 ){ |
︙ | ︙ | |||
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 | /* 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 | > > > | 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 | /* 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 | ** 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. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** 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. |
︙ | ︙ | |||
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | /* 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; | > > > > > > > > > > > > > > > > | 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 | /* 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 | ** 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. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** 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. ** |
︙ | ︙ | |||
696 697 698 699 700 701 702 703 704 705 706 707 708 709 | 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 ){ | > | 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 | 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 ){ |
︙ | ︙ | |||
729 730 731 732 733 734 735 736 737 738 739 740 741 742 | 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; | > | 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 | 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 | ** 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. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** 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: |
︙ | ︙ | |||
208 209 210 211 212 213 214 215 216 217 218 219 | 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 */ | > > > > > > > > > > > > > > > > > > > > > < < < < < < | 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 | 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 | ** 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. ** | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** 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> |
︙ | ︙ | |||
304 305 306 307 308 309 310 311 312 313 314 315 316 317 | /* ** 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 | > > > > > > > > > > > > > > > | 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 | /* ** 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 |
︙ | ︙ | |||
775 776 777 778 779 780 781 | ** 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; | | | 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 | ** 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; |
︙ | ︙ | |||
1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 | *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; | > | > > | 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 | *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); |
︙ | ︙ | |||
1577 1578 1579 1580 1581 1582 1583 | /* ** 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); | | | | 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 | /* ** 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 ** pPager. */ int sqlite3pager_pagecount(Pager *pPager){ i64 n; assert( pPager!=0 ); if( pPager->dbSize>=0 ){ 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; } |
︙ | ︙ | |||
1695 1696 1697 1698 1699 1700 1701 | if( pPager->errMask!=0 ){ rc = pager_errcode(pPager); return rc; } if( nPage>=(unsigned)pPager->dbSize ){ return SQLITE_OK; } | | | 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 | 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; |
︙ | ︙ | |||
1727 1728 1729 1730 1731 1732 1733 | int sqlite3pager_close(Pager *pPager){ PgHdr *pPg, *pNext; switch( pPager->state ){ case PAGER_RESERVED: case PAGER_SYNCED: case PAGER_EXCLUSIVE: { sqlite3pager_rollback(pPager); | | | | | 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 | 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; |
︙ | ︙ | |||
2062 2063 2064 2065 2066 2067 2068 | 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. */ | | | 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 | 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. |
︙ | ︙ | |||
2128 2129 2130 2131 2132 2133 2134 | return rc; } } pPg = 0; }else{ /* Search for page in cache */ pPg = pager_lookup(pPager, pgno); | | | | | | | 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 | 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{ |
︙ | ︙ | |||
2262 2263 2264 2265 2266 2267 2268 | rc = pager_errcode(pPager); return rc; } if( pPager->dbSize<(int)pgno ){ memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); }else{ int rc; | | | 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 | 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 |
︙ | ︙ | |||
2356 2357 2358 2359 2360 2361 2362 | } /* When all pages reach the freelist, drop the read lock from ** the database file. */ pPager->nRef--; assert( pPager->nRef>=0 ); | | | | 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 | } /* 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; } /* ** Create a journal file for pPager. There should already be a RESERVED ** 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; |
︙ | ︙ | |||
2457 2458 2459 2460 2461 2462 2463 | 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 ); | | | 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 | 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); |
︙ | ︙ | |||
2551 2552 2553 2554 2555 2556 2557 | 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. */ | | | | 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 | 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); } |
︙ | ︙ | |||
2609 2610 2611 2612 2613 2614 2615 | /* 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 ); | | | 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 | /* 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); |
︙ | ︙ | |||
2639 2640 2641 2642 2643 2644 2645 | page_add_to_stmt_list(pPg); } /* Update the database size and return. */ if( pPager->dbSize<(int)pPg->pgno ){ pPager->dbSize = pPg->pgno; | | | 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 | 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; } /* |
︙ | ︙ | |||
2702 2703 2704 2705 2706 2707 2708 | ** 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; | | | 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 | ** 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. |
︙ | ︙ | |||
2734 2735 2736 2737 2738 2739 2740 | ** 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; | | | 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 | ** 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); |
︙ | ︙ | |||
2790 2791 2792 2793 2794 2795 2796 | rc = pager_errcode(pPager); return rc; } if( pPager->state<PAGER_RESERVED ){ return SQLITE_ERROR; } TRACE2("COMMIT %d\n", pPager->fd.h); | | | 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 | 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; |
︙ | ︙ | |||
2851 2852 2853 2854 2855 2856 2857 | ** 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); | | | 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 | ** 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 ); |
︙ | ︙ | |||
2958 2959 2960 2961 2962 2963 2964 | */ 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); | | | 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 | */ 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; |
︙ | ︙ | |||
3006 3007 3008 3009 3010 3011 3012 | /* ** Commit a statement. */ int sqlite3pager_stmt_commit(Pager *pPager){ if( pPager->stmtInUse ){ PgHdr *pPg, *pNext; TRACE2("STMT-COMMIT %d\n", pPager->fd.h); | | | | | 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 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 | /* ** 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; pPager->pStmt = 0; } pPager->stmtAutoopen = 0; return SQLITE_OK; } /* ** 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; |
︙ | ︙ | |||
3144 3145 3146 3147 3148 3149 3150 | */ 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. */ | | | 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 | */ 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 | ** ************************************************************************* ** 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. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** 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 ){ |
︙ | ︙ | |||
77 78 79 80 81 82 83 | %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. | > | | | > < > | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | %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. |
︙ | ︙ | |||
140 141 142 143 144 145 146 | // 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 | | > > > > | 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | // 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 |
︙ | ︙ | |||
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 | // 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. | > > > > | 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 | // 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. |
︙ | ︙ | |||
788 789 790 791 792 793 794 795 796 797 798 799 800 801 | 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); } | > > | 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 | 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); } |
︙ | ︙ | |||
865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 | 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; } | > > > > | 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 | 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2003 April 6 ** ** The author disclaims copyright to this source code. In place of ** 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. ** ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2003 April 6 ** ** The author disclaims copyright to this source code. In place of ** 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. ** ************************************************************************* ** 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" |
︙ | ︙ | |||
440 441 442 443 444 445 446 447 448 449 450 451 452 453 | ++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); | > | 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 | ++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); |
︙ | ︙ | |||
473 474 475 476 477 478 479 480 481 482 483 484 485 486 | } ++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); | > | 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 | } ++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); |
︙ | ︙ | |||
503 504 505 506 507 508 509 510 511 512 513 514 515 516 | 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[] = { | > | 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 | 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[] = { |
︙ | ︙ | |||
627 628 629 630 631 632 633 634 635 636 637 638 639 640 | 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. ** | > > | 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 | 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 | ** 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. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** 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. |
︙ | ︙ | |||
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 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 | (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. */ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){ CollSeq *pRet; if( p->pPrior ){ pRet = multiSelectCollSeq(pParse, p->pPrior, iCol); }else{ 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. | > > > > > | 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 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 | (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. */ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){ CollSeq *pRet; if( p->pPrior ){ pRet = multiSelectCollSeq(pParse, p->pPrior, iCol); }else{ 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. |
︙ | ︙ | |||
1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 | 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 | > > | 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 | 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 |
︙ | ︙ | |||
1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 | 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: | > > | 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 | 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: |
︙ | ︙ | |||
2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 | /* 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; | > | 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 | /* 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; |
︙ | ︙ | |||
2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 | 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; | > > | 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 | 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; |
︙ | ︙ | |||
2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 | 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 ){ | > > | 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 | 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** 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. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** 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. ** ************************************************************************* ** 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 |
︙ | ︙ | |||
1255 1256 1257 1258 1259 1260 1261 | 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*); | > > | | > > > > | 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 | 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*); |
︙ | ︙ | |||
1293 1294 1295 1296 1297 1298 1299 | 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*); | < | 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 | 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*); |
︙ | ︙ | |||
1333 1334 1335 1336 1337 1338 1339 | 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); | > > | | | | | | | | | | | | | | | > > > > > > > > > | 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 | 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 | ** 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. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** 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> |
︙ | ︙ | |||
2487 2488 2489 2490 2491 2492 2493 | 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 | | | 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 | 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 |
︙ | ︙ | |||
2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 | 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; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | 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 | ** 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. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** 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> |
︙ | ︙ | |||
574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 | } 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; } | > > > > | 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 | } 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 | ************************************************************************* ** 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. ** | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ************************************************************************* ** 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> /* |
︙ | ︙ | |||
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 327 | *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; } case '?': { *tokenType = TK_VARIABLE; for(i=1; isdigit(z[i]); 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++; | > > > | 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 327 328 329 330 | *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; } case '?': { *tokenType = TK_VARIABLE; for(i=1; isdigit(z[i]); 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++; |
︙ | ︙ | |||
350 351 352 353 354 355 356 | }else{ break; } } if( n==0 ) *tokenType = TK_ILLEGAL; } return i; | | > > > | 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 | }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; break; } if( !isxdigit(c) ){ *tokenType = TK_ILLEGAL; return i; } } 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; |
︙ | ︙ | |||
498 499 500 501 502 503 504 | return nErr; } /* ** Token types used by the sqlite3_complete() routine. See the header ** comments on that procedure for additional information. */ | | | | | | | | | > > > | | < < < > > > | | | | | < < < > > > > | | | | | > | | | | | > > > > > > > > | > > | 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 | 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; } |
︙ | ︙ | |||
631 632 633 634 635 636 637 638 639 640 641 642 643 644 | } 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; } | > > > | 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 | } 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; } |
︙ | ︙ | |||
655 656 657 658 659 660 661 | token = tkOTHER; } break; } case 'e': case 'E': { if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){ token = tkEND; | > > | | > > > > > | 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 725 726 727 728 729 730 731 732 733 734 735 736 737 | 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; char const *zSql8; int rc = 0; pVal = sqlite3ValueNew(); sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC); 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 | ** 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; | > | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** 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; |
︙ | ︙ | |||
798 799 800 801 802 803 804 | sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger); } pTrigger = pTrigger->pNext; } return 0; } | > | 799 800 801 802 803 804 805 806 | 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 | ** 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. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** 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; |
︙ | ︙ | |||
63 64 65 66 67 68 69 70 | 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, | > > > > > | | > > > > > > > > > > > | 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 | 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 | ** ** 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. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** 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" /* |
︙ | ︙ | |||
3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 | */ 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 | > | 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 | */ 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 |
︙ | ︙ | |||
3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 | 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: { | > | 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 | 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 | 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); | > | > > | 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 | */ 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 ); | > > | 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 | */ 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 ); |
︙ | ︙ | |||
440 441 442 443 444 445 446 447 448 449 450 451 452 453 | 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){ | > | 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 | 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){ |
︙ | ︙ | |||
469 470 471 472 473 474 475 476 477 478 479 480 481 482 | 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". */ | > | 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 | 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". */ |
︙ | ︙ | |||
545 546 547 548 549 550 551 552 553 554 555 556 557 558 | 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; | > | 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 | 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 | # 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. # | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # 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 |
︙ | ︙ | |||
201 202 203 204 205 206 207 208 209 210 211 212 213 214 | 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; | > | 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | 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; |
︙ | ︙ | |||
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 | 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 { | > > > > > > > > > > > > > > > > > > > | 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 | 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 { |
︙ | ︙ | |||
430 431 432 433 434 435 436 | } {9 10} do_test attach-4.5 { execsql { INSERT INTO db2.t3 VALUES(9,10); SELECT * FROM db2.t3; } } {1 2 9 10} | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | } {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.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2003 October 31 # # The author disclaims copyright to this source code. In place of # 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. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing date and time functions. # | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # 2003 October 31 # # The author disclaims copyright to this source code. In place of # 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. # #*********************************************************************** # 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 | # 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 | > > > | > | | 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 , |
︙ | ︙ |