mirror of
https://github.com/status-im/sqlcipher.git
synced 2026-08-31 06:21:07 +00:00
Snapshot of upstream SQLite 3.25.0
This commit is contained in:
+120
-35
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user