mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-03 11:12:27 +00:00
Upgrade SQLite to 3.40 (#699)
This commit is contained in:
parent
bcae817215
commit
0dc0758574
151 changed files with 27917 additions and 22169 deletions
112
third_party/sqlite3/delete.c
vendored
112
third_party/sqlite3/delete.c
vendored
|
@ -12,9 +12,7 @@
|
|||
** This file contains C code routines that are called by the parser
|
||||
** in order to generate code for DELETE FROM statements.
|
||||
*/
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
|
||||
/* clang-format off */
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
|
||||
/*
|
||||
** While a SrcList can in general represent multiple tables and subqueries
|
||||
|
@ -46,6 +44,16 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
|
|||
return pTab;
|
||||
}
|
||||
|
||||
/* Generate byte-code that will report the number of rows modified
|
||||
** by a DELETE, INSERT, or UPDATE statement.
|
||||
*/
|
||||
void sqlite3CodeChangeCount(Vdbe *v, int regCounter, const char *zColName){
|
||||
sqlite3VdbeAddOp0(v, OP_FkCheck);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, regCounter, 1);
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zColName, SQLITE_STATIC);
|
||||
}
|
||||
|
||||
/* Return true if table pTab is read-only.
|
||||
**
|
||||
** A table is read-only if any of the following are true:
|
||||
|
@ -53,18 +61,42 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
|
|||
** 1) It is a virtual table and no implementation of the xUpdate method
|
||||
** has been provided
|
||||
**
|
||||
** 2) It is a system table (i.e. sqlite_schema), this call is not
|
||||
** 2) A trigger is currently being coded and the table is a virtual table
|
||||
** that is SQLITE_VTAB_DIRECTONLY or if PRAGMA trusted_schema=OFF and
|
||||
** the table is not SQLITE_VTAB_INNOCUOUS.
|
||||
**
|
||||
** 3) It is a system table (i.e. sqlite_schema), this call is not
|
||||
** part of a nested parse and writable_schema pragma has not
|
||||
** been specified
|
||||
**
|
||||
** 3) The table is a shadow table, the database connection is in
|
||||
** 4) The table is a shadow table, the database connection is in
|
||||
** defensive mode, and the current sqlite3_prepare()
|
||||
** is for a top-level SQL statement.
|
||||
*/
|
||||
static int vtabIsReadOnly(Parse *pParse, Table *pTab){
|
||||
if( sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ){
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Within triggers:
|
||||
** * Do not allow DELETE, INSERT, or UPDATE of SQLITE_VTAB_DIRECTONLY
|
||||
** virtual tables
|
||||
** * Only allow DELETE, INSERT, or UPDATE of non-SQLITE_VTAB_INNOCUOUS
|
||||
** virtual tables if PRAGMA trusted_schema=ON.
|
||||
*/
|
||||
if( pParse->pToplevel!=0
|
||||
&& pTab->u.vtab.p->eVtabRisk >
|
||||
((pParse->db->flags & SQLITE_TrustedSchema)!=0)
|
||||
){
|
||||
sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
|
||||
pTab->zName);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int tabIsReadOnly(Parse *pParse, Table *pTab){
|
||||
sqlite3 *db;
|
||||
if( IsVirtual(pTab) ){
|
||||
return sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0;
|
||||
return vtabIsReadOnly(pParse, pTab);
|
||||
}
|
||||
if( (pTab->tabFlags & (TF_Readonly|TF_Shadow))==0 ) return 0;
|
||||
db = pParse->db;
|
||||
|
@ -76,9 +108,11 @@ static int tabIsReadOnly(Parse *pParse, Table *pTab){
|
|||
}
|
||||
|
||||
/*
|
||||
** Check to make sure the given table is writable. If it is not
|
||||
** writable, generate an error message and return 1. If it is
|
||||
** writable return 0;
|
||||
** Check to make sure the given table is writable.
|
||||
**
|
||||
** If pTab is not writable -> generate an error message and return 1.
|
||||
** If pTab is writable but other errors have occurred -> return 1.
|
||||
** If pTab is writable and no prior errors -> return 0;
|
||||
*/
|
||||
int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
|
||||
if( tabIsReadOnly(pParse, pTab) ){
|
||||
|
@ -86,7 +120,7 @@ int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
|
|||
return 1;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_VIEW
|
||||
if( !viewOk && pTab->pSelect ){
|
||||
if( !viewOk && IsView(pTab) ){
|
||||
sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
|
||||
return 1;
|
||||
}
|
||||
|
@ -120,8 +154,8 @@ void sqlite3MaterializeView(
|
|||
assert( pFrom->nSrc==1 );
|
||||
pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
|
||||
pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
|
||||
assert( pFrom->a[0].pOn==0 );
|
||||
assert( pFrom->a[0].pUsing==0 );
|
||||
assert( pFrom->a[0].fg.isUsing==0 );
|
||||
assert( pFrom->a[0].u3.pOn==0 );
|
||||
}
|
||||
pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, pOrderBy,
|
||||
SF_IncludeHidden, pLimit);
|
||||
|
@ -190,13 +224,13 @@ Expr *sqlite3LimitWhere(
|
|||
}else{
|
||||
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
if( pPk->nKeyCol==1 ){
|
||||
const char *zName = pTab->aCol[pPk->aiColumn[0]].zName;
|
||||
const char *zName = pTab->aCol[pPk->aiColumn[0]].zCnName;
|
||||
pLhs = sqlite3Expr(db, TK_ID, zName);
|
||||
pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, zName));
|
||||
}else{
|
||||
int i;
|
||||
for(i=0; i<pPk->nKeyCol; i++){
|
||||
Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zName);
|
||||
Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zCnName);
|
||||
pEList = sqlite3ExprListAppend(pParse, pEList, p);
|
||||
}
|
||||
pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
|
||||
|
@ -212,6 +246,7 @@ Expr *sqlite3LimitWhere(
|
|||
pSelectSrc = sqlite3SrcListDup(db, pSrc, 0);
|
||||
pSrc->a[0].pTab = pTab;
|
||||
if( pSrc->a[0].fg.isIndexedBy ){
|
||||
assert( pSrc->a[0].fg.isCte==0 );
|
||||
pSrc->a[0].u2.pIBIndex = 0;
|
||||
pSrc->a[0].fg.isIndexedBy = 0;
|
||||
sqlite3DbFree(db, pSrc->a[0].u1.zIndexedBy);
|
||||
|
@ -284,12 +319,13 @@ void sqlite3DeleteFrom(
|
|||
|
||||
memset(&sContext, 0, sizeof(sContext));
|
||||
db = pParse->db;
|
||||
if( pParse->nErr || db->mallocFailed ){
|
||||
assert( db->pParse==pParse );
|
||||
if( pParse->nErr ){
|
||||
goto delete_from_cleanup;
|
||||
}
|
||||
assert( db->mallocFailed==0 );
|
||||
assert( pTabList->nSrc==1 );
|
||||
|
||||
|
||||
/* 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
|
||||
|
@ -303,7 +339,7 @@ void sqlite3DeleteFrom(
|
|||
*/
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
|
||||
isView = pTab->pSelect!=0;
|
||||
isView = IsView(pTab);
|
||||
#else
|
||||
# define pTrigger 0
|
||||
# define isView 0
|
||||
|
@ -314,6 +350,14 @@ void sqlite3DeleteFrom(
|
|||
# define isView 0
|
||||
#endif
|
||||
|
||||
#if TREETRACE_ENABLED
|
||||
if( sqlite3TreeTrace & 0x10000 ){
|
||||
sqlite3TreeViewLine(0, "In sqlite3Delete() at %s:%d", __FILE__, __LINE__);
|
||||
sqlite3TreeViewDelete(pParse->pWith, pTabList, pWhere,
|
||||
pOrderBy, pLimit, pTrigger);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
|
||||
if( !isView ){
|
||||
pWhere = sqlite3LimitWhere(
|
||||
|
@ -429,7 +473,11 @@ void sqlite3DeleteFrom(
|
|||
}
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
assert( pIdx->pSchema==pTab->pSchema );
|
||||
sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
|
||||
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
|
||||
sqlite3VdbeAddOp3(v, OP_Clear, pIdx->tnum, iDb, memCnt ? memCnt : -1);
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
|
||||
}
|
||||
}
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
|
||||
|
@ -464,7 +512,7 @@ void sqlite3DeleteFrom(
|
|||
** ONEPASS_SINGLE: One-pass approach - at most one row deleted.
|
||||
** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted.
|
||||
*/
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,0,wcf,iTabCur+1);
|
||||
if( pWInfo==0 ) goto delete_from_cleanup;
|
||||
eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
|
||||
assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI );
|
||||
|
@ -550,7 +598,7 @@ void sqlite3DeleteFrom(
|
|||
if( eOnePass!=ONEPASS_OFF ){
|
||||
assert( nKey==nPk ); /* OP_Found will use an unpacked key */
|
||||
if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){
|
||||
assert( pPk!=0 || pTab->pSelect!=0 );
|
||||
assert( pPk!=0 || IsView(pTab) );
|
||||
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
|
@ -617,9 +665,7 @@ void sqlite3DeleteFrom(
|
|||
** invoke the callback function.
|
||||
*/
|
||||
if( memCnt ){
|
||||
sqlite3VdbeAddOp2(v, OP_ChngCntRow, memCnt, 1);
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC);
|
||||
sqlite3CodeChangeCount(v, memCnt, "rows deleted");
|
||||
}
|
||||
|
||||
delete_from_cleanup:
|
||||
|
@ -630,7 +676,7 @@ delete_from_cleanup:
|
|||
sqlite3ExprListDelete(db, pOrderBy);
|
||||
sqlite3ExprDelete(db, pLimit);
|
||||
#endif
|
||||
sqlite3DbFree(db, aToOpen);
|
||||
if( aToOpen ) sqlite3DbNNFreeNN(db, aToOpen);
|
||||
return;
|
||||
}
|
||||
/* Make sure "isView" and other macros defined above are undefined. Otherwise
|
||||
|
@ -784,7 +830,7 @@ void sqlite3GenerateRowDelete(
|
|||
** the update-hook is not invoked for rows removed by REPLACE, but the
|
||||
** pre-update-hook is.
|
||||
*/
|
||||
if( pTab->pSelect==0 ){
|
||||
if( !IsView(pTab) ){
|
||||
u8 p5 = 0;
|
||||
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek);
|
||||
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
|
||||
|
@ -941,13 +987,15 @@ int sqlite3GenerateIndexKey(
|
|||
continue;
|
||||
}
|
||||
sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iDataCur, j, regBase+j);
|
||||
/* If the column affinity is REAL but the number is an integer, then it
|
||||
** might be stored in the table as an integer (using a compact
|
||||
** representation) then converted to REAL by an OP_RealAffinity opcode.
|
||||
** But we are getting ready to store this value back into an index, where
|
||||
** it should be converted by to INTEGER again. So omit the OP_RealAffinity
|
||||
** opcode if it is present */
|
||||
sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity);
|
||||
if( pIdx->aiColumn[j]>=0 ){
|
||||
/* If the column affinity is REAL but the number is an integer, then it
|
||||
** might be stored in the table as an integer (using a compact
|
||||
** representation) then converted to REAL by an OP_RealAffinity opcode.
|
||||
** But we are getting ready to store this value back into an index, where
|
||||
** it should be converted by to INTEGER again. So omit the
|
||||
** OP_RealAffinity opcode if it is present */
|
||||
sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity);
|
||||
}
|
||||
}
|
||||
if( regOut ){
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue