Snapshot of upstream SQLite 3.25.0

This commit is contained in:
Stephen Lombardo
2018-09-18 12:31:37 -04:00
parent 1f3bc22483
commit bf3fa86130
558 changed files with 76379 additions and 20890 deletions
+120 -35
View File
@@ -25,6 +25,8 @@ void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){
sqlite3ExprListDelete(db, pTmp->pExprList);
sqlite3SelectDelete(db, pTmp->pSelect);
sqlite3IdListDelete(db, pTmp->pIdList);
sqlite3UpsertDelete(db, pTmp->pUpsert);
sqlite3DbFree(db, pTmp->zSpan);
sqlite3DbFree(db, pTmp);
}
@@ -179,14 +181,16 @@ void sqlite3BeginTrigger(
goto trigger_cleanup;
}
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){
if( !noErr ){
sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
}else{
assert( !db->init.busy );
sqlite3CodeVerifySchema(pParse, iDb);
if( !IN_RENAME_OBJECT ){
if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){
if( !noErr ){
sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
}else{
assert( !db->init.busy );
sqlite3CodeVerifySchema(pParse, iDb);
}
goto trigger_cleanup;
}
goto trigger_cleanup;
}
/* Do not create a trigger on a system table */
@@ -210,7 +214,7 @@ void sqlite3BeginTrigger(
}
#ifndef SQLITE_OMIT_AUTHORIZATION
{
if( !IN_RENAME_OBJECT ){
int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
int code = SQLITE_CREATE_TRIGGER;
const char *zDb = db->aDb[iTabDb].zDbSName;
@@ -244,8 +248,15 @@ void sqlite3BeginTrigger(
pTrigger->pTabSchema = pTab->pSchema;
pTrigger->op = (u8)op;
pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
pTrigger->pColumns = sqlite3IdListDup(db, pColumns);
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, pTrigger->table, pTableName->a[0].zName);
pTrigger->pWhen = pWhen;
pWhen = 0;
}else{
pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
}
pTrigger->pColumns = pColumns;
pColumns = 0;
assert( pParse->pNewTrigger==0 );
pParse->pNewTrigger = pTrigger;
@@ -294,6 +305,14 @@ void sqlite3FinishTrigger(
goto triggerfinish_cleanup;
}
#ifndef SQLITE_OMIT_ALTERTABLE
if( IN_RENAME_OBJECT ){
assert( !db->init.busy );
pParse->pNewTrigger = pTrig;
pTrig = 0;
}else
#endif
/* if we are not initializing,
** build the sqlite_master entry
*/
@@ -335,10 +354,21 @@ void sqlite3FinishTrigger(
triggerfinish_cleanup:
sqlite3DeleteTrigger(db, pTrig);
assert( !pParse->pNewTrigger );
assert( IN_RENAME_OBJECT || !pParse->pNewTrigger );
sqlite3DeleteTriggerStep(db, pStepList);
}
/*
** Duplicate a range of text from an SQL statement, then convert all
** whitespace characters into ordinary space characters.
*/
static char *triggerSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){
char *z = sqlite3DbSpanDup(db, zStart, zEnd);
int i;
if( z ) for(i=0; z[i]; i++) if( sqlite3Isspace(z[i]) ) z[i] = ' ';
return z;
}
/*
** Turn a SELECT statement (that the pSelect parameter points to) into
** a trigger step. Return a pointer to a TriggerStep structure.
@@ -346,7 +376,12 @@ triggerfinish_cleanup:
** The parser calls this routine when it finds a SELECT statement in
** body of a TRIGGER.
*/
TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){
TriggerStep *sqlite3TriggerSelectStep(
sqlite3 *db, /* Database connection */
Select *pSelect, /* The SELECT statement */
const char *zStart, /* Start of SQL text */
const char *zEnd /* End of SQL text */
){
TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
if( pTriggerStep==0 ) {
sqlite3SelectDelete(db, pSelect);
@@ -355,6 +390,7 @@ TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){
pTriggerStep->op = TK_SELECT;
pTriggerStep->pSelect = pSelect;
pTriggerStep->orconf = OE_Default;
pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd);
return pTriggerStep;
}
@@ -365,10 +401,13 @@ TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){
** If an OOM error occurs, NULL is returned and db->mallocFailed is set.
*/
static TriggerStep *triggerStepAllocate(
sqlite3 *db, /* Database connection */
Parse *pParse, /* Parser context */
u8 op, /* Trigger opcode */
Token *pName /* The target name */
Token *pName, /* The target name */
const char *zStart, /* Start of SQL text */
const char *zEnd /* End of SQL text */
){
sqlite3 *db = pParse->db;
TriggerStep *pTriggerStep;
pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1);
@@ -378,6 +417,10 @@ static TriggerStep *triggerStepAllocate(
sqlite3Dequote(z);
pTriggerStep->zTarget = z;
pTriggerStep->op = op;
pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd);
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenMap(pParse, pTriggerStep->zTarget, pName);
}
}
return pTriggerStep;
}
@@ -390,23 +433,36 @@ static TriggerStep *triggerStepAllocate(
** body of a trigger.
*/
TriggerStep *sqlite3TriggerInsertStep(
sqlite3 *db, /* The database connection */
Parse *pParse, /* Parser */
Token *pTableName, /* Name of the table into which we insert */
IdList *pColumn, /* List of columns in pTableName to insert into */
Select *pSelect, /* A SELECT statement that supplies values */
u8 orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
u8 orconf, /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
Upsert *pUpsert, /* ON CONFLICT clauses for upsert */
const char *zStart, /* Start of SQL text */
const char *zEnd /* End of SQL text */
){
sqlite3 *db = pParse->db;
TriggerStep *pTriggerStep;
assert(pSelect != 0 || db->mallocFailed);
pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName);
pTriggerStep = triggerStepAllocate(pParse, TK_INSERT, pTableName,zStart,zEnd);
if( pTriggerStep ){
pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
if( IN_RENAME_OBJECT ){
pTriggerStep->pSelect = pSelect;
pSelect = 0;
}else{
pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
}
pTriggerStep->pIdList = pColumn;
pTriggerStep->pUpsert = pUpsert;
pTriggerStep->orconf = orconf;
}else{
testcase( pColumn );
sqlite3IdListDelete(db, pColumn);
testcase( pUpsert );
sqlite3UpsertDelete(db, pUpsert);
}
sqlite3SelectDelete(db, pSelect);
@@ -419,18 +475,28 @@ TriggerStep *sqlite3TriggerInsertStep(
** sees an UPDATE statement inside the body of a CREATE TRIGGER.
*/
TriggerStep *sqlite3TriggerUpdateStep(
sqlite3 *db, /* The database connection */
Parse *pParse, /* Parser */
Token *pTableName, /* Name of the table to be updated */
ExprList *pEList, /* The SET clause: list of column and new values */
Expr *pWhere, /* The WHERE clause */
u8 orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
u8 orconf, /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
const char *zStart, /* Start of SQL text */
const char *zEnd /* End of SQL text */
){
sqlite3 *db = pParse->db;
TriggerStep *pTriggerStep;
pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName);
pTriggerStep = triggerStepAllocate(pParse, TK_UPDATE, pTableName,zStart,zEnd);
if( pTriggerStep ){
pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
if( IN_RENAME_OBJECT ){
pTriggerStep->pExprList = pEList;
pTriggerStep->pWhere = pWhere;
pEList = 0;
pWhere = 0;
}else{
pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
}
pTriggerStep->orconf = orconf;
}
sqlite3ExprListDelete(db, pEList);
@@ -444,15 +510,23 @@ TriggerStep *sqlite3TriggerUpdateStep(
** sees a DELETE statement inside the body of a CREATE TRIGGER.
*/
TriggerStep *sqlite3TriggerDeleteStep(
sqlite3 *db, /* Database connection */
Parse *pParse, /* Parser */
Token *pTableName, /* The table from which rows are deleted */
Expr *pWhere /* The WHERE clause */
Expr *pWhere, /* The WHERE clause */
const char *zStart, /* Start of SQL text */
const char *zEnd /* End of SQL text */
){
sqlite3 *db = pParse->db;
TriggerStep *pTriggerStep;
pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName);
pTriggerStep = triggerStepAllocate(pParse, TK_DELETE, pTableName,zStart,zEnd);
if( pTriggerStep ){
pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
if( IN_RENAME_OBJECT ){
pTriggerStep->pWhere = pWhere;
pWhere = 0;
}else{
pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
}
pTriggerStep->orconf = OE_Default;
}
sqlite3ExprDelete(db, pWhere);
@@ -585,7 +659,7 @@ void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
*pp = (*pp)->pNext;
}
sqlite3DeleteTrigger(db, pTrigger);
db->flags |= SQLITE_InternChanges;
db->mDbFlags |= DBFLAG_SchemaChange;
}
}
@@ -705,13 +779,21 @@ static int codeTriggerProgram(
pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf;
assert( pParse->okConstFactor==0 );
#ifndef SQLITE_OMIT_TRACE
if( pStep->zSpan ){
sqlite3VdbeAddOp4(v, OP_Trace, 0x7fffffff, 1, 0,
sqlite3MPrintf(db, "-- %s", pStep->zSpan),
P4_DYNAMIC);
}
#endif
switch( pStep->op ){
case TK_UPDATE: {
sqlite3Update(pParse,
targetSrcList(pParse, pStep),
sqlite3ExprListDup(db, pStep->pExprList, 0),
sqlite3ExprDup(db, pStep->pWhere, 0),
pParse->eOrconf
pParse->eOrconf, 0, 0, 0
);
break;
}
@@ -720,14 +802,15 @@ static int codeTriggerProgram(
targetSrcList(pParse, pStep),
sqlite3SelectDup(db, pStep->pSelect, 0),
sqlite3IdListDup(db, pStep->pIdList),
pParse->eOrconf
pParse->eOrconf,
sqlite3UpsertDup(db, pStep->pUpsert)
);
break;
}
case TK_DELETE: {
sqlite3DeleteFrom(pParse,
targetSrcList(pParse, pStep),
sqlite3ExprDup(db, pStep->pWhere, 0)
sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0
);
break;
}
@@ -845,9 +928,11 @@ static TriggerPrg *codeRowTrigger(
pTab->zName
));
#ifndef SQLITE_OMIT_TRACE
sqlite3VdbeChangeP4(v, -1,
sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC
);
if( pTrigger->zName ){
sqlite3VdbeChangeP4(v, -1,
sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC
);
}
#endif
/* If one was specified, code the WHEN clause. If it evaluates to false
@@ -875,7 +960,7 @@ static TriggerPrg *codeRowTrigger(
VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf)));
transferParseError(pParse, pSubParse);
if( db->mallocFailed==0 ){
if( db->mallocFailed==0 && pParse->nErr==0 ){
pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg);
}
pProgram->nMem = pSubParse->nMem;