| OLD | NEW |
| 1 /* | 1 /* |
| 2 ** | 2 ** |
| 3 ** The author disclaims copyright to this source code. In place of | 3 ** The author disclaims copyright to this source code. In place of |
| 4 ** a legal notice, here is a blessing: | 4 ** a legal notice, here is a blessing: |
| 5 ** | 5 ** |
| 6 ** May you do good and not evil. | 6 ** May you do good and not evil. |
| 7 ** May you find forgiveness for yourself and forgive others. | 7 ** May you find forgiveness for yourself and forgive others. |
| 8 ** May you share freely, never taking more than you give. | 8 ** May you share freely, never taking more than you give. |
| 9 ** | 9 ** |
| 10 ************************************************************************* | 10 ************************************************************************* |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 break; | 242 break; |
| 243 } | 243 } |
| 244 }else{ | 244 }else{ |
| 245 /* If zKey is non-NULL, then this foreign key was declared to | 245 /* If zKey is non-NULL, then this foreign key was declared to |
| 246 ** map to an explicit list of columns in table pParent. Check if this | 246 ** map to an explicit list of columns in table pParent. Check if this |
| 247 ** index matches those columns. Also, check that the index uses | 247 ** index matches those columns. Also, check that the index uses |
| 248 ** the default collation sequences for each column. */ | 248 ** the default collation sequences for each column. */ |
| 249 int i, j; | 249 int i, j; |
| 250 for(i=0; i<nCol; i++){ | 250 for(i=0; i<nCol; i++){ |
| 251 i16 iCol = pIdx->aiColumn[i]; /* Index of column in parent tbl */ | 251 i16 iCol = pIdx->aiColumn[i]; /* Index of column in parent tbl */ |
| 252 char *zDfltColl; /* Def. collation for column */ | 252 const char *zDfltColl; /* Def. collation for column */ |
| 253 char *zIdxCol; /* Name of indexed column */ | 253 char *zIdxCol; /* Name of indexed column */ |
| 254 | 254 |
| 255 if( iCol<0 ) break; /* No foreign keys against expression indexes */ |
| 256 |
| 255 /* If the index uses a collation sequence that is different from | 257 /* If the index uses a collation sequence that is different from |
| 256 ** the default collation sequence for the column, this index is | 258 ** the default collation sequence for the column, this index is |
| 257 ** unusable. Bail out early in this case. */ | 259 ** unusable. Bail out early in this case. */ |
| 258 zDfltColl = pParent->aCol[iCol].zColl; | 260 zDfltColl = pParent->aCol[iCol].zColl; |
| 259 if( !zDfltColl ){ | 261 if( !zDfltColl ) zDfltColl = sqlite3StrBINARY; |
| 260 zDfltColl = "BINARY"; | |
| 261 } | |
| 262 if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break; | 262 if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break; |
| 263 | 263 |
| 264 zIdxCol = pParent->aCol[iCol].zName; | 264 zIdxCol = pParent->aCol[iCol].zName; |
| 265 for(j=0; j<nCol; j++){ | 265 for(j=0; j<nCol; j++){ |
| 266 if( sqlite3StrICmp(pFKey->aCol[j].zCol, zIdxCol)==0 ){ | 266 if( sqlite3StrICmp(pFKey->aCol[j].zCol, zIdxCol)==0 ){ |
| 267 if( aiCol ) aiCol[i] = pFKey->aCol[j].iFrom; | 267 if( aiCol ) aiCol[i] = pFKey->aCol[j].iFrom; |
| 268 break; | 268 break; |
| 269 } | 269 } |
| 270 } | 270 } |
| 271 if( j==nCol ) break; | 271 if( j==nCol ) break; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 ** to increment the constraint-counter (i.e. this is an INSERT operation), | 367 ** to increment the constraint-counter (i.e. this is an INSERT operation), |
| 368 ** then check if the row being inserted matches itself. If so, do not | 368 ** then check if the row being inserted matches itself. If so, do not |
| 369 ** increment the constraint-counter. */ | 369 ** increment the constraint-counter. */ |
| 370 if( pTab==pFKey->pFrom && nIncr==1 ){ | 370 if( pTab==pFKey->pFrom && nIncr==1 ){ |
| 371 sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp); VdbeCoverage(v); | 371 sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp); VdbeCoverage(v); |
| 372 sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); | 372 sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); |
| 373 } | 373 } |
| 374 | 374 |
| 375 sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); | 375 sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); |
| 376 sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp); VdbeCoverage(v); | 376 sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp); VdbeCoverage(v); |
| 377 sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk); | 377 sqlite3VdbeGoto(v, iOk); |
| 378 sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); | 378 sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); |
| 379 sqlite3VdbeJumpHere(v, iMustBeInt); | 379 sqlite3VdbeJumpHere(v, iMustBeInt); |
| 380 sqlite3ReleaseTempReg(pParse, regTemp); | 380 sqlite3ReleaseTempReg(pParse, regTemp); |
| 381 }else{ | 381 }else{ |
| 382 int nCol = pFKey->nCol; | 382 int nCol = pFKey->nCol; |
| 383 int regTemp = sqlite3GetTempRange(pParse, nCol); | 383 int regTemp = sqlite3GetTempRange(pParse, nCol); |
| 384 int regRec = sqlite3GetTempReg(pParse); | 384 int regRec = sqlite3GetTempReg(pParse); |
| 385 | 385 |
| 386 sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb); | 386 sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb); |
| 387 sqlite3VdbeSetP4KeyInfo(pParse, pIdx); | 387 sqlite3VdbeSetP4KeyInfo(pParse, pIdx); |
| 388 for(i=0; i<nCol; i++){ | 388 for(i=0; i<nCol; i++){ |
| 389 sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i]+1+regData, regTemp+i); | 389 sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i]+1+regData, regTemp+i); |
| 390 } | 390 } |
| 391 | 391 |
| 392 /* If the parent table is the same as the child table, and we are about | 392 /* If the parent table is the same as the child table, and we are about |
| 393 ** to increment the constraint-counter (i.e. this is an INSERT operation), | 393 ** to increment the constraint-counter (i.e. this is an INSERT operation), |
| 394 ** then check if the row being inserted matches itself. If so, do not | 394 ** then check if the row being inserted matches itself. If so, do not |
| 395 ** increment the constraint-counter. | 395 ** increment the constraint-counter. |
| 396 ** | 396 ** |
| 397 ** If any of the parent-key values are NULL, then the row cannot match | 397 ** If any of the parent-key values are NULL, then the row cannot match |
| 398 ** itself. So set JUMPIFNULL to make sure we do the OP_Found if any | 398 ** itself. So set JUMPIFNULL to make sure we do the OP_Found if any |
| 399 ** of the parent-key values are NULL (at this point it is known that | 399 ** of the parent-key values are NULL (at this point it is known that |
| 400 ** none of the child key values are). | 400 ** none of the child key values are). |
| 401 */ | 401 */ |
| 402 if( pTab==pFKey->pFrom && nIncr==1 ){ | 402 if( pTab==pFKey->pFrom && nIncr==1 ){ |
| 403 int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1; | 403 int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1; |
| 404 for(i=0; i<nCol; i++){ | 404 for(i=0; i<nCol; i++){ |
| 405 int iChild = aiCol[i]+1+regData; | 405 int iChild = aiCol[i]+1+regData; |
| 406 int iParent = pIdx->aiColumn[i]+1+regData; | 406 int iParent = pIdx->aiColumn[i]+1+regData; |
| 407 assert( pIdx->aiColumn[i]>=0 ); |
| 407 assert( aiCol[i]!=pTab->iPKey ); | 408 assert( aiCol[i]!=pTab->iPKey ); |
| 408 if( pIdx->aiColumn[i]==pTab->iPKey ){ | 409 if( pIdx->aiColumn[i]==pTab->iPKey ){ |
| 409 /* The parent key is a composite key that includes the IPK column */ | 410 /* The parent key is a composite key that includes the IPK column */ |
| 410 iParent = regData; | 411 iParent = regData; |
| 411 } | 412 } |
| 412 sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); VdbeCoverage(v); | 413 sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); VdbeCoverage(v); |
| 413 sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); | 414 sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); |
| 414 } | 415 } |
| 415 sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk); | 416 sqlite3VdbeGoto(v, iOk); |
| 416 } | 417 } |
| 417 | 418 |
| 418 sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec, | 419 sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec, |
| 419 sqlite3IndexAffinityStr(v,pIdx), nCol); | 420 sqlite3IndexAffinityStr(pParse->db,pIdx), nCol); |
| 420 sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); VdbeCoverage(v); | 421 sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); VdbeCoverage(v); |
| 421 | 422 |
| 422 sqlite3ReleaseTempReg(pParse, regRec); | 423 sqlite3ReleaseTempReg(pParse, regRec); |
| 423 sqlite3ReleaseTempRange(pParse, regTemp, nCol); | 424 sqlite3ReleaseTempRange(pParse, regTemp, nCol); |
| 424 } | 425 } |
| 425 } | 426 } |
| 426 | 427 |
| 427 if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferFKs) | 428 if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferFKs) |
| 428 && !pParse->pToplevel | 429 && !pParse->pToplevel |
| 429 && !pParse->isMultiWrite | 430 && !pParse->isMultiWrite |
| 430 ){ | 431 ){ |
| 431 /* Special case: If this is an INSERT statement that will insert exactly | 432 /* Special case: If this is an INSERT statement that will insert exactly |
| 432 ** one row into the table, raise a constraint immediately instead of | 433 ** one row into the table, raise a constraint immediately instead of |
| 433 ** incrementing a counter. This is necessary as the VM code is being | 434 ** incrementing a counter. This is necessary as the VM code is being |
| 434 ** generated for will not open a statement transaction. */ | 435 ** generated for will not open a statement transaction. */ |
| 435 assert( nIncr==1 ); | 436 assert( nIncr==1 ); |
| 436 sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, | 437 sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, |
| 437 OE_Abort, 0, P4_STATIC, P5_ConstraintFK); | 438 OE_Abort, 0, P4_STATIC, P5_ConstraintFK); |
| 438 }else{ | 439 }else{ |
| 439 if( nIncr>0 && pFKey->isDeferred==0 ){ | 440 if( nIncr>0 && pFKey->isDeferred==0 ){ |
| 440 sqlite3ParseToplevel(pParse)->mayAbort = 1; | 441 sqlite3MayAbort(pParse); |
| 441 } | 442 } |
| 442 sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); | 443 sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); |
| 443 } | 444 } |
| 444 | 445 |
| 445 sqlite3VdbeResolveLabel(v, iOk); | 446 sqlite3VdbeResolveLabel(v, iOk); |
| 446 sqlite3VdbeAddOp1(v, OP_Close, iCur); | 447 sqlite3VdbeAddOp1(v, OP_Close, iCur); |
| 447 } | 448 } |
| 448 | 449 |
| 449 | 450 |
| 450 /* | 451 /* |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 return pExpr; | 503 return pExpr; |
| 503 } | 504 } |
| 504 | 505 |
| 505 /* | 506 /* |
| 506 ** This function is called to generate code executed when a row is deleted | 507 ** This function is called to generate code executed when a row is deleted |
| 507 ** from the parent table of foreign key constraint pFKey and, if pFKey is | 508 ** from the parent table of foreign key constraint pFKey and, if pFKey is |
| 508 ** deferred, when a row is inserted into the same table. When generating | 509 ** deferred, when a row is inserted into the same table. When generating |
| 509 ** code for an SQL UPDATE operation, this function may be called twice - | 510 ** code for an SQL UPDATE operation, this function may be called twice - |
| 510 ** once to "delete" the old row and once to "insert" the new row. | 511 ** once to "delete" the old row and once to "insert" the new row. |
| 511 ** | 512 ** |
| 513 ** Parameter nIncr is passed -1 when inserting a row (as this may decrease |
| 514 ** the number of FK violations in the db) or +1 when deleting one (as this |
| 515 ** may increase the number of FK constraint problems). |
| 516 ** |
| 512 ** The code generated by this function scans through the rows in the child | 517 ** The code generated by this function scans through the rows in the child |
| 513 ** table that correspond to the parent table row being deleted or inserted. | 518 ** table that correspond to the parent table row being deleted or inserted. |
| 514 ** For each child row found, one of the following actions is taken: | 519 ** For each child row found, one of the following actions is taken: |
| 515 ** | 520 ** |
| 516 ** Operation | FK type | Action taken | 521 ** Operation | FK type | Action taken |
| 517 ** -------------------------------------------------------------------------- | 522 ** -------------------------------------------------------------------------- |
| 518 ** DELETE immediate Increment the "immediate constraint counter". | 523 ** DELETE immediate Increment the "immediate constraint counter". |
| 519 ** Or, if the ON (UPDATE|DELETE) action is RESTRICT, | 524 ** Or, if the ON (UPDATE|DELETE) action is RESTRICT, |
| 520 ** throw a "FOREIGN KEY constraint failed" exception. | 525 ** throw a "FOREIGN KEY constraint failed" exception. |
| 521 ** | 526 ** |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 if( HasRowid(pTab) ){ | 606 if( HasRowid(pTab) ){ |
| 602 pLeft = exprTableRegister(pParse, pTab, regData, -1); | 607 pLeft = exprTableRegister(pParse, pTab, regData, -1); |
| 603 pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, -1); | 608 pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, -1); |
| 604 pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight, 0); | 609 pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight, 0); |
| 605 }else{ | 610 }else{ |
| 606 Expr *pEq, *pAll = 0; | 611 Expr *pEq, *pAll = 0; |
| 607 Index *pPk = sqlite3PrimaryKeyIndex(pTab); | 612 Index *pPk = sqlite3PrimaryKeyIndex(pTab); |
| 608 assert( pIdx!=0 ); | 613 assert( pIdx!=0 ); |
| 609 for(i=0; i<pPk->nKeyCol; i++){ | 614 for(i=0; i<pPk->nKeyCol; i++){ |
| 610 i16 iCol = pIdx->aiColumn[i]; | 615 i16 iCol = pIdx->aiColumn[i]; |
| 616 assert( iCol>=0 ); |
| 611 pLeft = exprTableRegister(pParse, pTab, regData, iCol); | 617 pLeft = exprTableRegister(pParse, pTab, regData, iCol); |
| 612 pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol); | 618 pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol); |
| 613 pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0); | 619 pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0); |
| 614 pAll = sqlite3ExprAnd(db, pAll, pEq); | 620 pAll = sqlite3ExprAnd(db, pAll, pEq); |
| 615 } | 621 } |
| 616 pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0, 0); | 622 pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0, 0); |
| 617 } | 623 } |
| 618 pWhere = sqlite3ExprAnd(db, pWhere, pNe); | 624 pWhere = sqlite3ExprAnd(db, pWhere, pNe); |
| 619 } | 625 } |
| 620 | 626 |
| 621 /* Resolve the references in the WHERE clause. */ | 627 /* Resolve the references in the WHERE clause. */ |
| 622 memset(&sNameContext, 0, sizeof(NameContext)); | 628 memset(&sNameContext, 0, sizeof(NameContext)); |
| 623 sNameContext.pSrcList = pSrc; | 629 sNameContext.pSrcList = pSrc; |
| 624 sNameContext.pParse = pParse; | 630 sNameContext.pParse = pParse; |
| 625 sqlite3ResolveExprNames(&sNameContext, pWhere); | 631 sqlite3ResolveExprNames(&sNameContext, pWhere); |
| 626 | 632 |
| 627 /* Create VDBE to loop through the entries in pSrc that match the WHERE | 633 /* Create VDBE to loop through the entries in pSrc that match the WHERE |
| 628 ** clause. If the constraint is not deferred, throw an exception for | 634 ** clause. For each row found, increment either the deferred or immediate |
| 629 ** each row found. Otherwise, for deferred constraints, increment the | 635 ** foreign key constraint counter. */ |
| 630 ** deferred constraint counter by nIncr for each row selected. */ | |
| 631 pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0); | 636 pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0); |
| 632 if( nIncr>0 && pFKey->isDeferred==0 ){ | |
| 633 sqlite3ParseToplevel(pParse)->mayAbort = 1; | |
| 634 } | |
| 635 sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); | 637 sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); |
| 636 if( pWInfo ){ | 638 if( pWInfo ){ |
| 637 sqlite3WhereEnd(pWInfo); | 639 sqlite3WhereEnd(pWInfo); |
| 638 } | 640 } |
| 639 | 641 |
| 640 /* Clean up the WHERE clause constructed above. */ | 642 /* Clean up the WHERE clause constructed above. */ |
| 641 sqlite3ExprDelete(db, pWhere); | 643 sqlite3ExprDelete(db, pWhere); |
| 642 if( iFkIfZero ){ | 644 if( iFkIfZero ){ |
| 643 sqlite3VdbeJumpHere(v, iFkIfZero); | 645 sqlite3VdbeJumpHere(v, iFkIfZero); |
| 644 } | 646 } |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 804 }else if( pCol->colFlags & COLFLAG_PRIMKEY ){ | 806 }else if( pCol->colFlags & COLFLAG_PRIMKEY ){ |
| 805 return 1; | 807 return 1; |
| 806 } | 808 } |
| 807 } | 809 } |
| 808 } | 810 } |
| 809 } | 811 } |
| 810 return 0; | 812 return 0; |
| 811 } | 813 } |
| 812 | 814 |
| 813 /* | 815 /* |
| 816 ** Return true if the parser passed as the first argument is being |
| 817 ** used to code a trigger that is really a "SET NULL" action belonging |
| 818 ** to trigger pFKey. |
| 819 */ |
| 820 static int isSetNullAction(Parse *pParse, FKey *pFKey){ |
| 821 Parse *pTop = sqlite3ParseToplevel(pParse); |
| 822 if( pTop->pTriggerPrg ){ |
| 823 Trigger *p = pTop->pTriggerPrg->pTrigger; |
| 824 if( (p==pFKey->apTrigger[0] && pFKey->aAction[0]==OE_SetNull) |
| 825 || (p==pFKey->apTrigger[1] && pFKey->aAction[1]==OE_SetNull) |
| 826 ){ |
| 827 return 1; |
| 828 } |
| 829 } |
| 830 return 0; |
| 831 } |
| 832 |
| 833 /* |
| 814 ** This function is called when inserting, deleting or updating a row of | 834 ** This function is called when inserting, deleting or updating a row of |
| 815 ** table pTab to generate VDBE code to perform foreign key constraint | 835 ** table pTab to generate VDBE code to perform foreign key constraint |
| 816 ** processing for the operation. | 836 ** processing for the operation. |
| 817 ** | 837 ** |
| 818 ** For a DELETE operation, parameter regOld is passed the index of the | 838 ** For a DELETE operation, parameter regOld is passed the index of the |
| 819 ** first register in an array of (pTab->nCol+1) registers containing the | 839 ** first register in an array of (pTab->nCol+1) registers containing the |
| 820 ** rowid of the row being deleted, followed by each of the column values | 840 ** rowid of the row being deleted, followed by each of the column values |
| 821 ** of the row being deleted, from left to right. Parameter regNew is passed | 841 ** of the row being deleted, from left to right. Parameter regNew is passed |
| 822 ** zero in this case. | 842 ** zero in this case. |
| 823 ** | 843 ** |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 855 | 875 |
| 856 /* Loop through all the foreign key constraints for which pTab is the | 876 /* Loop through all the foreign key constraints for which pTab is the |
| 857 ** child table (the table that the foreign key definition is part of). */ | 877 ** child table (the table that the foreign key definition is part of). */ |
| 858 for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ | 878 for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ |
| 859 Table *pTo; /* Parent table of foreign key pFKey */ | 879 Table *pTo; /* Parent table of foreign key pFKey */ |
| 860 Index *pIdx = 0; /* Index on key columns in pTo */ | 880 Index *pIdx = 0; /* Index on key columns in pTo */ |
| 861 int *aiFree = 0; | 881 int *aiFree = 0; |
| 862 int *aiCol; | 882 int *aiCol; |
| 863 int iCol; | 883 int iCol; |
| 864 int i; | 884 int i; |
| 865 int isIgnore = 0; | 885 int bIgnore = 0; |
| 866 | 886 |
| 867 if( aChange | 887 if( aChange |
| 868 && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0 | 888 && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0 |
| 869 && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0 | 889 && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0 |
| 870 ){ | 890 ){ |
| 871 continue; | 891 continue; |
| 872 } | 892 } |
| 873 | 893 |
| 874 /* Find the parent table of this foreign key. Also find a unique index | 894 /* Find the parent table of this foreign key. Also find a unique index |
| 875 ** on the parent key columns in the parent table. If either of these | 895 ** on the parent key columns in the parent table. If either of these |
| (...skipping 30 matching lines...) Expand all Loading... |
| 906 if( aiFree ){ | 926 if( aiFree ){ |
| 907 aiCol = aiFree; | 927 aiCol = aiFree; |
| 908 }else{ | 928 }else{ |
| 909 iCol = pFKey->aCol[0].iFrom; | 929 iCol = pFKey->aCol[0].iFrom; |
| 910 aiCol = &iCol; | 930 aiCol = &iCol; |
| 911 } | 931 } |
| 912 for(i=0; i<pFKey->nCol; i++){ | 932 for(i=0; i<pFKey->nCol; i++){ |
| 913 if( aiCol[i]==pTab->iPKey ){ | 933 if( aiCol[i]==pTab->iPKey ){ |
| 914 aiCol[i] = -1; | 934 aiCol[i] = -1; |
| 915 } | 935 } |
| 936 assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); |
| 916 #ifndef SQLITE_OMIT_AUTHORIZATION | 937 #ifndef SQLITE_OMIT_AUTHORIZATION |
| 917 /* Request permission to read the parent key columns. If the | 938 /* Request permission to read the parent key columns. If the |
| 918 ** authorization callback returns SQLITE_IGNORE, behave as if any | 939 ** authorization callback returns SQLITE_IGNORE, behave as if any |
| 919 ** values read from the parent table are NULL. */ | 940 ** values read from the parent table are NULL. */ |
| 920 if( db->xAuth ){ | 941 if( db->xAuth ){ |
| 921 int rcauth; | 942 int rcauth; |
| 922 char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName; | 943 char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName; |
| 923 rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb); | 944 rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb); |
| 924 isIgnore = (rcauth==SQLITE_IGNORE); | 945 bIgnore = (rcauth==SQLITE_IGNORE); |
| 925 } | 946 } |
| 926 #endif | 947 #endif |
| 927 } | 948 } |
| 928 | 949 |
| 929 /* Take a shared-cache advisory read-lock on the parent table. Allocate | 950 /* Take a shared-cache advisory read-lock on the parent table. Allocate |
| 930 ** a cursor to use to search the unique index on the parent key columns | 951 ** a cursor to use to search the unique index on the parent key columns |
| 931 ** in the parent table. */ | 952 ** in the parent table. */ |
| 932 sqlite3TableLock(pParse, iDb, pTo->tnum, 0, pTo->zName); | 953 sqlite3TableLock(pParse, iDb, pTo->tnum, 0, pTo->zName); |
| 933 pParse->nTab++; | 954 pParse->nTab++; |
| 934 | 955 |
| 935 if( regOld!=0 ){ | 956 if( regOld!=0 ){ |
| 936 /* A row is being removed from the child table. Search for the parent. | 957 /* A row is being removed from the child table. Search for the parent. |
| 937 ** If the parent does not exist, removing the child row resolves an | 958 ** If the parent does not exist, removing the child row resolves an |
| 938 ** outstanding foreign key constraint violation. */ | 959 ** outstanding foreign key constraint violation. */ |
| 939 fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1,isIgnore); | 960 fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1, bIgnore); |
| 940 } | 961 } |
| 941 if( regNew!=0 ){ | 962 if( regNew!=0 && !isSetNullAction(pParse, pFKey) ){ |
| 942 /* A row is being added to the child table. If a parent row cannot | 963 /* A row is being added to the child table. If a parent row cannot |
| 943 ** be found, adding the child row has violated the FK constraint. */ | 964 ** be found, adding the child row has violated the FK constraint. |
| 944 fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1,isIgnore); | 965 ** |
| 966 ** If this operation is being performed as part of a trigger program |
| 967 ** that is actually a "SET NULL" action belonging to this very |
| 968 ** foreign key, then omit this scan altogether. As all child key |
| 969 ** values are guaranteed to be NULL, it is not possible for adding |
| 970 ** this row to cause an FK violation. */ |
| 971 fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1, bIgnore); |
| 945 } | 972 } |
| 946 | 973 |
| 947 sqlite3DbFree(db, aiFree); | 974 sqlite3DbFree(db, aiFree); |
| 948 } | 975 } |
| 949 | 976 |
| 950 /* Loop through all the foreign key constraints that refer to this table. | 977 /* Loop through all the foreign key constraints that refer to this table. |
| 951 ** (the "child" constraints) */ | 978 ** (the "child" constraints) */ |
| 952 for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){ | 979 for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){ |
| 953 Index *pIdx = 0; /* Foreign key index for pFKey */ | 980 Index *pIdx = 0; /* Foreign key index for pFKey */ |
| 954 SrcList *pSrc; | 981 SrcList *pSrc; |
| 955 int *aiCol = 0; | 982 int *aiCol = 0; |
| 956 | 983 |
| 957 if( aChange && fkParentIsModified(pTab, pFKey, aChange, bChngRowid)==0 ){ | 984 if( aChange && fkParentIsModified(pTab, pFKey, aChange, bChngRowid)==0 ){ |
| 958 continue; | 985 continue; |
| 959 } | 986 } |
| 960 | 987 |
| 961 if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) | 988 if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) |
| 962 && !pParse->pToplevel && !pParse->isMultiWrite | 989 && !pParse->pToplevel && !pParse->isMultiWrite |
| 963 ){ | 990 ){ |
| 964 assert( regOld==0 && regNew!=0 ); | 991 assert( regOld==0 && regNew!=0 ); |
| 965 /* Inserting a single row into a parent table cannot cause an immediate | 992 /* Inserting a single row into a parent table cannot cause (or fix) |
| 966 ** foreign key violation. So do nothing in this case. */ | 993 ** an immediate foreign key violation. So do nothing in this case. */ |
| 967 continue; | 994 continue; |
| 968 } | 995 } |
| 969 | 996 |
| 970 if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ | 997 if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ |
| 971 if( !isIgnoreErrors || db->mallocFailed ) return; | 998 if( !isIgnoreErrors || db->mallocFailed ) return; |
| 972 continue; | 999 continue; |
| 973 } | 1000 } |
| 974 assert( aiCol || pFKey->nCol==1 ); | 1001 assert( aiCol || pFKey->nCol==1 ); |
| 975 | 1002 |
| 976 /* Create a SrcList structure containing the child table. We need the | 1003 /* Create a SrcList structure containing the child table. We need the |
| 977 ** child table as a SrcList for sqlite3WhereBegin() */ | 1004 ** child table as a SrcList for sqlite3WhereBegin() */ |
| 978 pSrc = sqlite3SrcListAppend(db, 0, 0, 0); | 1005 pSrc = sqlite3SrcListAppend(db, 0, 0, 0); |
| 979 if( pSrc ){ | 1006 if( pSrc ){ |
| 980 struct SrcList_item *pItem = pSrc->a; | 1007 struct SrcList_item *pItem = pSrc->a; |
| 981 pItem->pTab = pFKey->pFrom; | 1008 pItem->pTab = pFKey->pFrom; |
| 982 pItem->zName = pFKey->pFrom->zName; | 1009 pItem->zName = pFKey->pFrom->zName; |
| 983 pItem->pTab->nRef++; | 1010 pItem->pTab->nRef++; |
| 984 pItem->iCursor = pParse->nTab++; | 1011 pItem->iCursor = pParse->nTab++; |
| 985 | 1012 |
| 986 if( regNew!=0 ){ | 1013 if( regNew!=0 ){ |
| 987 fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1); | 1014 fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1); |
| 988 } | 1015 } |
| 989 if( regOld!=0 ){ | 1016 if( regOld!=0 ){ |
| 990 /* If there is a RESTRICT action configured for the current operation | 1017 int eAction = pFKey->aAction[aChange!=0]; |
| 991 ** on the parent table of this FK, then throw an exception | |
| 992 ** immediately if the FK constraint is violated, even if this is a | |
| 993 ** deferred trigger. That's what RESTRICT means. To defer checking | |
| 994 ** the constraint, the FK should specify NO ACTION (represented | |
| 995 ** using OE_None). NO ACTION is the default. */ | |
| 996 fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1); | 1018 fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1); |
| 1019 /* If this is a deferred FK constraint, or a CASCADE or SET NULL |
| 1020 ** action applies, then any foreign key violations caused by |
| 1021 ** removing the parent key will be rectified by the action trigger. |
| 1022 ** So do not set the "may-abort" flag in this case. |
| 1023 ** |
| 1024 ** Note 1: If the FK is declared "ON UPDATE CASCADE", then the |
| 1025 ** may-abort flag will eventually be set on this statement anyway |
| 1026 ** (when this function is called as part of processing the UPDATE |
| 1027 ** within the action trigger). |
| 1028 ** |
| 1029 ** Note 2: At first glance it may seem like SQLite could simply omit |
| 1030 ** all OP_FkCounter related scans when either CASCADE or SET NULL |
| 1031 ** applies. The trouble starts if the CASCADE or SET NULL action |
| 1032 ** trigger causes other triggers or action rules attached to the |
| 1033 ** child table to fire. In these cases the fk constraint counters |
| 1034 ** might be set incorrectly if any OP_FkCounter related scans are |
| 1035 ** omitted. */ |
| 1036 if( !pFKey->isDeferred && eAction!=OE_Cascade && eAction!=OE_SetNull ){ |
| 1037 sqlite3MayAbort(pParse); |
| 1038 } |
| 997 } | 1039 } |
| 998 pItem->zName = 0; | 1040 pItem->zName = 0; |
| 999 sqlite3SrcListDelete(db, pSrc); | 1041 sqlite3SrcListDelete(db, pSrc); |
| 1000 } | 1042 } |
| 1001 sqlite3DbFree(db, aiCol); | 1043 sqlite3DbFree(db, aiCol); |
| 1002 } | 1044 } |
| 1003 } | 1045 } |
| 1004 | 1046 |
| 1005 #define COLUMN_MASK(x) (((x)>31) ? 0xffffffff : ((u32)1<<(x))) | 1047 #define COLUMN_MASK(x) (((x)>31) ? 0xffffffff : ((u32)1<<(x))) |
| 1006 | 1048 |
| 1007 /* | 1049 /* |
| 1008 ** This function is called before generating code to update or delete a | 1050 ** This function is called before generating code to update or delete a |
| 1009 ** row contained in table pTab. | 1051 ** row contained in table pTab. |
| 1010 */ | 1052 */ |
| 1011 u32 sqlite3FkOldmask( | 1053 u32 sqlite3FkOldmask( |
| 1012 Parse *pParse, /* Parse context */ | 1054 Parse *pParse, /* Parse context */ |
| 1013 Table *pTab /* Table being modified */ | 1055 Table *pTab /* Table being modified */ |
| 1014 ){ | 1056 ){ |
| 1015 u32 mask = 0; | 1057 u32 mask = 0; |
| 1016 if( pParse->db->flags&SQLITE_ForeignKeys ){ | 1058 if( pParse->db->flags&SQLITE_ForeignKeys ){ |
| 1017 FKey *p; | 1059 FKey *p; |
| 1018 int i; | 1060 int i; |
| 1019 for(p=pTab->pFKey; p; p=p->pNextFrom){ | 1061 for(p=pTab->pFKey; p; p=p->pNextFrom){ |
| 1020 for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom); | 1062 for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom); |
| 1021 } | 1063 } |
| 1022 for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ | 1064 for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ |
| 1023 Index *pIdx = 0; | 1065 Index *pIdx = 0; |
| 1024 sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0); | 1066 sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0); |
| 1025 if( pIdx ){ | 1067 if( pIdx ){ |
| 1026 for(i=0; i<pIdx->nKeyCol; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]); | 1068 for(i=0; i<pIdx->nKeyCol; i++){ |
| 1069 assert( pIdx->aiColumn[i]>=0 ); |
| 1070 mask |= COLUMN_MASK(pIdx->aiColumn[i]); |
| 1071 } |
| 1027 } | 1072 } |
| 1028 } | 1073 } |
| 1029 } | 1074 } |
| 1030 return mask; | 1075 return mask; |
| 1031 } | 1076 } |
| 1032 | 1077 |
| 1033 | 1078 |
| 1034 /* | 1079 /* |
| 1035 ** This function is called before generating code to update or delete a | 1080 ** This function is called before generating code to update or delete a |
| 1036 ** row contained in table pTab. If the operation is a DELETE, then | 1081 ** row contained in table pTab. If the operation is a DELETE, then |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1138 for(i=0; i<pFKey->nCol; i++){ | 1183 for(i=0; i<pFKey->nCol; i++){ |
| 1139 Token tOld = { "old", 3 }; /* Literal "old" token */ | 1184 Token tOld = { "old", 3 }; /* Literal "old" token */ |
| 1140 Token tNew = { "new", 3 }; /* Literal "new" token */ | 1185 Token tNew = { "new", 3 }; /* Literal "new" token */ |
| 1141 Token tFromCol; /* Name of column in child table */ | 1186 Token tFromCol; /* Name of column in child table */ |
| 1142 Token tToCol; /* Name of column in parent table */ | 1187 Token tToCol; /* Name of column in parent table */ |
| 1143 int iFromCol; /* Idx of column in child table */ | 1188 int iFromCol; /* Idx of column in child table */ |
| 1144 Expr *pEq; /* tFromCol = OLD.tToCol */ | 1189 Expr *pEq; /* tFromCol = OLD.tToCol */ |
| 1145 | 1190 |
| 1146 iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; | 1191 iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; |
| 1147 assert( iFromCol>=0 ); | 1192 assert( iFromCol>=0 ); |
| 1148 tToCol.z = pIdx ? pTab->aCol[pIdx->aiColumn[i]].zName : "oid"; | 1193 assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) ); |
| 1194 assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); |
| 1195 tToCol.z = pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName; |
| 1149 tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName; | 1196 tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName; |
| 1150 | 1197 |
| 1151 tToCol.n = sqlite3Strlen30(tToCol.z); | 1198 tToCol.n = sqlite3Strlen30(tToCol.z); |
| 1152 tFromCol.n = sqlite3Strlen30(tFromCol.z); | 1199 tFromCol.n = sqlite3Strlen30(tFromCol.z); |
| 1153 | 1200 |
| 1154 /* Create the expression "OLD.zToCol = zFromCol". It is important | 1201 /* Create the expression "OLD.zToCol = zFromCol". It is important |
| 1155 ** that the "OLD.zToCol" term is on the LHS of the = operator, so | 1202 ** that the "OLD.zToCol" term is on the LHS of the = operator, so |
| 1156 ** that the affinity and collation sequence associated with the | 1203 ** that the affinity and collation sequence associated with the |
| 1157 ** parent table are used for the comparison. */ | 1204 ** parent table are used for the comparison. */ |
| 1158 pEq = sqlite3PExpr(pParse, TK_EQ, | 1205 pEq = sqlite3PExpr(pParse, TK_EQ, |
| 1159 sqlite3PExpr(pParse, TK_DOT, | 1206 sqlite3PExpr(pParse, TK_DOT, |
| 1160 sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld), | 1207 sqlite3ExprAlloc(db, TK_ID, &tOld, 0), |
| 1161 sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol) | 1208 sqlite3ExprAlloc(db, TK_ID, &tToCol, 0) |
| 1162 , 0), | 1209 , 0), |
| 1163 sqlite3PExpr(pParse, TK_ID, 0, 0, &tFromCol) | 1210 sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0) |
| 1164 , 0); | 1211 , 0); |
| 1165 pWhere = sqlite3ExprAnd(db, pWhere, pEq); | 1212 pWhere = sqlite3ExprAnd(db, pWhere, pEq); |
| 1166 | 1213 |
| 1167 /* For ON UPDATE, construct the next term of the WHEN clause. | 1214 /* For ON UPDATE, construct the next term of the WHEN clause. |
| 1168 ** The final WHEN clause will be like this: | 1215 ** The final WHEN clause will be like this: |
| 1169 ** | 1216 ** |
| 1170 ** WHEN NOT(old.col1 IS new.col1 AND ... AND old.colN IS new.colN) | 1217 ** WHEN NOT(old.col1 IS new.col1 AND ... AND old.colN IS new.colN) |
| 1171 */ | 1218 */ |
| 1172 if( pChanges ){ | 1219 if( pChanges ){ |
| 1173 pEq = sqlite3PExpr(pParse, TK_IS, | 1220 pEq = sqlite3PExpr(pParse, TK_IS, |
| 1174 sqlite3PExpr(pParse, TK_DOT, | 1221 sqlite3PExpr(pParse, TK_DOT, |
| 1175 sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld), | 1222 sqlite3ExprAlloc(db, TK_ID, &tOld, 0), |
| 1176 sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol), | 1223 sqlite3ExprAlloc(db, TK_ID, &tToCol, 0), |
| 1177 0), | 1224 0), |
| 1178 sqlite3PExpr(pParse, TK_DOT, | 1225 sqlite3PExpr(pParse, TK_DOT, |
| 1179 sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew), | 1226 sqlite3ExprAlloc(db, TK_ID, &tNew, 0), |
| 1180 sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol), | 1227 sqlite3ExprAlloc(db, TK_ID, &tToCol, 0), |
| 1181 0), | 1228 0), |
| 1182 0); | 1229 0); |
| 1183 pWhen = sqlite3ExprAnd(db, pWhen, pEq); | 1230 pWhen = sqlite3ExprAnd(db, pWhen, pEq); |
| 1184 } | 1231 } |
| 1185 | 1232 |
| 1186 if( action!=OE_Restrict && (action!=OE_Cascade || pChanges) ){ | 1233 if( action!=OE_Restrict && (action!=OE_Cascade || pChanges) ){ |
| 1187 Expr *pNew; | 1234 Expr *pNew; |
| 1188 if( action==OE_Cascade ){ | 1235 if( action==OE_Cascade ){ |
| 1189 pNew = sqlite3PExpr(pParse, TK_DOT, | 1236 pNew = sqlite3PExpr(pParse, TK_DOT, |
| 1190 sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew), | 1237 sqlite3ExprAlloc(db, TK_ID, &tNew, 0), |
| 1191 sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol) | 1238 sqlite3ExprAlloc(db, TK_ID, &tToCol, 0) |
| 1192 , 0); | 1239 , 0); |
| 1193 }else if( action==OE_SetDflt ){ | 1240 }else if( action==OE_SetDflt ){ |
| 1194 Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt; | 1241 Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt; |
| 1195 if( pDflt ){ | 1242 if( pDflt ){ |
| 1196 pNew = sqlite3ExprDup(db, pDflt, 0); | 1243 pNew = sqlite3ExprDup(db, pDflt, 0); |
| 1197 }else{ | 1244 }else{ |
| 1198 pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); | 1245 pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); |
| 1199 } | 1246 } |
| 1200 }else{ | 1247 }else{ |
| 1201 pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); | 1248 pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1228 pWhere = 0; | 1275 pWhere = 0; |
| 1229 } | 1276 } |
| 1230 | 1277 |
| 1231 /* Disable lookaside memory allocation */ | 1278 /* Disable lookaside memory allocation */ |
| 1232 enableLookaside = db->lookaside.bEnabled; | 1279 enableLookaside = db->lookaside.bEnabled; |
| 1233 db->lookaside.bEnabled = 0; | 1280 db->lookaside.bEnabled = 0; |
| 1234 | 1281 |
| 1235 pTrigger = (Trigger *)sqlite3DbMallocZero(db, | 1282 pTrigger = (Trigger *)sqlite3DbMallocZero(db, |
| 1236 sizeof(Trigger) + /* struct Trigger */ | 1283 sizeof(Trigger) + /* struct Trigger */ |
| 1237 sizeof(TriggerStep) + /* Single step in trigger program */ | 1284 sizeof(TriggerStep) + /* Single step in trigger program */ |
| 1238 nFrom + 1 /* Space for pStep->target.z */ | 1285 nFrom + 1 /* Space for pStep->zTarget */ |
| 1239 ); | 1286 ); |
| 1240 if( pTrigger ){ | 1287 if( pTrigger ){ |
| 1241 pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1]; | 1288 pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1]; |
| 1242 pStep->target.z = (char *)&pStep[1]; | 1289 pStep->zTarget = (char *)&pStep[1]; |
| 1243 pStep->target.n = nFrom; | 1290 memcpy((char *)pStep->zTarget, zFrom, nFrom); |
| 1244 memcpy((char *)pStep->target.z, zFrom, nFrom); | |
| 1245 | 1291 |
| 1246 pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); | 1292 pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); |
| 1247 pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE); | 1293 pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE); |
| 1248 pStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); | 1294 pStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); |
| 1249 if( pWhen ){ | 1295 if( pWhen ){ |
| 1250 pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0, 0); | 1296 pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0, 0); |
| 1251 pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); | 1297 pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); |
| 1252 } | 1298 } |
| 1253 } | 1299 } |
| 1254 | 1300 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1353 #ifndef SQLITE_OMIT_TRIGGER | 1399 #ifndef SQLITE_OMIT_TRIGGER |
| 1354 fkTriggerDelete(db, pFKey->apTrigger[0]); | 1400 fkTriggerDelete(db, pFKey->apTrigger[0]); |
| 1355 fkTriggerDelete(db, pFKey->apTrigger[1]); | 1401 fkTriggerDelete(db, pFKey->apTrigger[1]); |
| 1356 #endif | 1402 #endif |
| 1357 | 1403 |
| 1358 pNext = pFKey->pNextFrom; | 1404 pNext = pFKey->pNextFrom; |
| 1359 sqlite3DbFree(db, pFKey); | 1405 sqlite3DbFree(db, pFKey); |
| 1360 } | 1406 } |
| 1361 } | 1407 } |
| 1362 #endif /* ifndef SQLITE_OMIT_FOREIGN_KEY */ | 1408 #endif /* ifndef SQLITE_OMIT_FOREIGN_KEY */ |
| OLD | NEW |