Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add opcodes OP_ResultRow and OP_RegMakeRec which are register-based equivalents to OP_Callback and OP_MakeRecord. Use the new opcodes. (CVS 4656) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
4c7f35da7751c61a9b61b1d95adddcc3 |
User & Date: | drh 2008-01-02 14:28:13.000 |
Context
2008-01-02
| ||
16:27 | Combine the eDest and iParm arguments to sqlite3Select() into a single type - "SelectDest". (CVS 4657) (check-in: 86dcdfe6d7 user: danielk1977 tags: trunk) | |
14:28 | Add opcodes OP_ResultRow and OP_RegMakeRec which are register-based equivalents to OP_Callback and OP_MakeRecord. Use the new opcodes. (CVS 4656) (check-in: 4c7f35da77 user: drh tags: trunk) | |
13:05 | Remove a surplus OP_Close from delete.c. Fixes a problem with (4654). (CVS 4655) (check-in: 03cc91b3b0 user: drh tags: trunk) | |
Changes
Changes to src/analyze.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2005 July 8 ** ** 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 associated with the ANALYZE command. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2005 July 8 ** ** 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 associated with the ANALYZE command. ** ** @(#) $Id: analyze.c,v 1.26 2008/01/02 14:28:13 drh Exp $ */ #ifndef SQLITE_OMIT_ANALYZE #include "sqliteInt.h" /* ** This routine generates code that opens the sqlite_stat1 table on cursor ** iStatCur. |
︙ | ︙ | |||
145 146 147 148 149 150 151 | ** Cells iMem through iMem+nCol are initialized to 0. The others ** are initialized to NULL. */ for(i=0; i<=nCol; i++){ sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem+i); } for(i=0; i<nCol; i++){ | | | 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | ** Cells iMem through iMem+nCol are initialized to 0. The others ** are initialized to NULL. */ for(i=0; i<=nCol; i++){ sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem+i); } for(i=0; i<nCol; i++){ sqlite3VdbeAddOp(v, OP_MemNull, 0, iMem+nCol+i+1); } /* Do the analysis. */ endOfLoop = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_Rewind, iIdxCur, endOfLoop); topOfLoop = sqlite3VdbeCurrentAddr(v); |
︙ | ︙ |
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.323 2008/01/02 14:28:13 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Return the 'affinity' of the expression pExpr if any. ** |
︙ | ︙ | |||
1794 1795 1796 1797 1798 1799 1800 | case TK_SELECT: { /* This has to be a scalar SELECT. Generate code to put the ** value of this select in a memory cell and record the number ** of the memory cell in iColumn. */ static const Token one = { (u8*)"1", 0, 1 }; Select *pSel; | < > < > | > | 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 | case TK_SELECT: { /* This has to be a scalar SELECT. Generate code to put the ** value of this select in a memory cell and record the number ** of the memory cell in iColumn. */ static const Token one = { (u8*)"1", 0, 1 }; Select *pSel; int sop; int iMem; pSel = pExpr->pSelect; iMem = pParse->nMem++; if( pExpr->op==TK_SELECT ){ sop = SRT_Mem; sqlite3VdbeAddOp(v, OP_MemNull, 0, iMem); VdbeComment((v, "Init subquery result")); }else{ sop = SRT_Exists; sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem); VdbeComment((v, "Init EXISTS result")); } sqlite3ExprDelete(pSel->pLimit); pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &one); if( sqlite3Select(pParse, pSel, sop, iMem, 0, 0, 0, 0) ){ return; } pExpr->iColumn = iMem; break; } } if( testAddr ){ sqlite3VdbeJumpHere(v, testAddr); } |
︙ | ︙ |
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.375 2008/01/02 14:28:13 drh Exp $ */ #include "sqliteInt.h" /* ** Delete all the content of a Select structure but do not deallocate ** the select structure itself. |
︙ | ︙ | |||
432 433 434 435 436 437 438 | ** stack are distinct. iTab is a sorting index that holds previously ** seen combinations of the N values. A new entry is made in iTab ** if the current N values are new. ** ** A jump to addrRepeat is made and the N+1 values are popped from the ** stack if the top N elements are not distinct. */ | | > > > > > > > > > > > > > > > > > > > > > > > | 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 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 | ** stack are distinct. iTab is a sorting index that holds previously ** seen combinations of the N values. A new entry is made in iTab ** if the current N values are new. ** ** A jump to addrRepeat is made and the N+1 values are popped from the ** stack if the top N elements are not distinct. */ static void codeDistinct_OLD( Vdbe *v, /* Generate code into this VM */ int iTab, /* A sorting index used to test for distinctness */ int addrRepeat, /* Jump to here if not distinct */ int N /* The top N elements of the stack must be distinct */ ){ sqlite3VdbeAddOp(v, OP_MakeRecord, -N, 0); sqlite3VdbeAddOp(v, OP_Distinct, iTab, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp(v, OP_Pop, N+1, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, addrRepeat); VdbeComment((v, "skip indistinct records")); sqlite3VdbeAddOp(v, OP_IdxInsert, iTab, 0); } /* ** Add code that will check to make sure the top N elements of the ** stack are distinct. iTab is a sorting index that holds previously ** seen combinations of the N values. A new entry is made in iTab ** if the current N values are new. ** ** A jump to addrRepeat is made and the N+1 values are popped from the ** stack if the top N elements are not distinct. */ static void codeDistinct( Vdbe *v, /* Generate code into this VM */ int iTab, /* A sorting index used to test for distinctness */ int addrRepeat, /* Jump to here if not distinct */ int iMem /* First element */ ){ sqlite3VdbeAddOp(v, OP_RegMakeRec, iMem, 0); sqlite3VdbeAddOp(v, OP_Distinct, iTab, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, addrRepeat); VdbeComment((v, "skip indistinct records")); sqlite3VdbeAddOp(v, OP_IdxInsert, iTab, 0); } /* ** Generate an error message when a SELECT is used within a subexpression |
︙ | ︙ | |||
486 487 488 489 490 491 492 | int eDest, /* How to dispose of the results */ int iParm, /* An argument to the disposal method */ int iContinue, /* Jump here to continue with next row */ int iBreak, /* Jump here to break out of the inner loop */ char *aff /* affinity string if eDest is SRT_Union */ ){ Vdbe *v = pParse->pVdbe; | | > > > > > > > > > | < > | | > > | | | | < < < | > | < > | > | < | 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 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 | int eDest, /* How to dispose of the results */ int iParm, /* An argument to the disposal method */ int iContinue, /* Jump here to continue with next row */ int iBreak, /* Jump here to break out of the inner loop */ char *aff /* affinity string if eDest is SRT_Union */ ){ Vdbe *v = pParse->pVdbe; int i, n; int hasDistinct; /* True if the DISTINCT keyword is present */ int iMem; /* Start of memory holding result set */ if( v==0 ) return 0; assert( pEList!=0 ); /* If there was a LIMIT clause on the SELECT statement, then do the check ** to see if this row should be output. */ hasDistinct = distinct>=0 && pEList->nExpr>0; if( pOrderBy==0 && !hasDistinct ){ codeOffset(v, p, iContinue, 0); } /* Pull the requested columns. */ if( nColumn>0 ){ n = nColumn; }else{ n = pEList->nExpr; } iMem = pParse->nMem; pParse->nMem += n+1; sqlite3VdbeAddOp(v, OP_MemInt, n, iMem); if( nColumn>0 ){ for(i=0; i<nColumn; i++){ sqlite3VdbeOp3Int(v, OP_Column, srcTab, i, iMem+i+1); } }else{ for(i=0; i<n; i++){ sqlite3ExprIntoReg(pParse, pEList->a[i].pExpr, iMem+i+1); } } nColumn = n; /* If the DISTINCT keyword was present on the SELECT statement ** and this row has been seen before, then do not make this row ** part of the result. */ if( hasDistinct ){ assert( pEList!=0 ); assert( pEList->nExpr==nColumn ); codeDistinct(v, distinct, iContinue, iMem); if( pOrderBy==0 ){ codeOffset(v, p, iContinue, nColumn); } } if( checkForMultiColumnSelectError(pParse, eDest, pEList->nExpr) ){ return 0; } switch( eDest ){ /* In this mode, write each query result to the key of the temporary ** table iParm. */ #ifndef SQLITE_OMIT_COMPOUND_SELECT case SRT_Union: { sqlite3VdbeAddOp(v, OP_RegMakeRec, iMem, 0); if( aff ){ sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC); } sqlite3VdbeAddOp(v, OP_IdxInsert, iParm, 0); break; } /* Construct a record from the query result, but instead of ** saving that record, use it as a key to delete elements from ** the temporary table iParm. */ case SRT_Except: { int addr; addr = sqlite3VdbeAddOp(v, OP_RegMakeRec, iMem, 0); sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC); sqlite3VdbeAddOp(v, OP_NotFound, iParm, addr+3); sqlite3VdbeAddOp(v, OP_Delete, iParm, 0); break; } #endif /* Store the result as data using a unique key. */ case SRT_Table: case SRT_EphemTab: { sqlite3VdbeAddOp(v, OP_RegMakeRec, iMem, 0); if( pOrderBy ){ pushOntoSorter(pParse, pOrderBy, p); }else{ sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); sqlite3VdbeAddOp(v, OP_Insert, iParm, OPFLAG_APPEND); } break; } #ifndef SQLITE_OMIT_SUBQUERY /* If we are creating a set for an "expr IN (SELECT ...)" construct, ** then there should be a single item on the stack. Write this ** item into the set table with bogus data. */ case SRT_Set: { int addr2; assert( nColumn==1 ); addr2 = sqlite3VdbeAddOp(v, OP_IfMemNull, iMem+1, 0); p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr,(iParm>>16)&0xff); if( pOrderBy ){ /* At first glance you would think we could optimize out the ** ORDER BY in this case since the order of entries in the set ** does not matter. But there might be a LIMIT clause, in which ** case the order does matter */ sqlite3VdbeAddOp(v, OP_MemLoad, iMem+1, 0); pushOntoSorter(pParse, pOrderBy, p); }else{ sqlite3VdbeOp3(v, OP_RegMakeRec, iMem, 0, &p->affinity, 1); sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0); } sqlite3VdbeJumpHere(v, addr2); break; } /* If any row exist in the result set, record that fact and abort. */ case SRT_Exists: { sqlite3VdbeAddOp(v, OP_MemInt, 1, iParm); /* The LIMIT clause will terminate the loop for us */ break; } /* If this is a scalar select that is part of an expression, then ** store the results in the appropriate memory cell and break out ** of the scan loop. */ case SRT_Mem: { assert( nColumn==1 ); sqlite3VdbeAddOp(v, OP_MemLoad, iMem+1, 0); if( pOrderBy ){ pushOntoSorter(pParse, pOrderBy, p); }else{ sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); /* The LIMIT clause will jump out of the loop for us */ } break; } #endif /* #ifndef SQLITE_OMIT_SUBQUERY */ /* Send the data to the callback function or to a subroutine. In the ** case of a subroutine, the subroutine itself is responsible for ** popping the data from the stack. */ case SRT_Subroutine: case SRT_Callback: { if( pOrderBy ){ sqlite3VdbeAddOp(v, OP_RegMakeRec, iMem, 0); pushOntoSorter(pParse, pOrderBy, p); }else if( eDest==SRT_Subroutine ){ for(i=0; i<nColumn; i++) sqlite3VdbeAddOp(v, OP_MemLoad, iMem+i+1, 0); sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm); }else{ sqlite3VdbeAddOp(v, OP_ResultRow, iMem+1, nColumn); } break; } #if !defined(SQLITE_OMIT_TRIGGER) /* Discard the results. This is used for SELECT statements inside ** the body of a TRIGGER. The purpose of such selects is to call ** user-defined functions that have side effects. We do not care ** about the actual results of the select. */ default: { assert( eDest==SRT_Discard ); break; } #endif } /* Jump to the end of the loop if the LIMIT is reached. */ |
︙ | ︙ | |||
2872 2873 2874 2875 2876 2877 2878 | Vdbe *v = pParse->pVdbe; int i; struct AggInfo_func *pFunc; if( pAggInfo->nFunc+pAggInfo->nColumn==0 ){ return; } for(i=0; i<pAggInfo->nColumn; i++){ | | | | 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 | Vdbe *v = pParse->pVdbe; int i; struct AggInfo_func *pFunc; if( pAggInfo->nFunc+pAggInfo->nColumn==0 ){ return; } for(i=0; i<pAggInfo->nColumn; i++){ sqlite3VdbeAddOp(v, OP_MemNull, 0, pAggInfo->aCol[i].iMem); } for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){ sqlite3VdbeAddOp(v, OP_MemNull, 0, pFunc->iMem); if( pFunc->iDistinct>=0 ){ Expr *pE = pFunc->pExpr; if( pE->pList==0 || pE->pList->nExpr!=1 ){ sqlite3ErrorMsg(pParse, "DISTINCT in aggregate must be followed " "by an expression"); pFunc->iDistinct = -1; }else{ |
︙ | ︙ | |||
2930 2931 2932 2933 2934 2935 2936 | sqlite3ExprCodeExprList(pParse, pList); }else{ nArg = 0; } if( pF->iDistinct>=0 ){ addrNext = sqlite3VdbeMakeLabel(v); assert( nArg==1 ); | | | 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 | sqlite3ExprCodeExprList(pParse, pList); }else{ nArg = 0; } if( pF->iDistinct>=0 ){ addrNext = sqlite3VdbeMakeLabel(v); assert( nArg==1 ); codeDistinct_OLD(v, pF->iDistinct, addrNext, 1); } if( pF->pFunc->needCollSeq ){ CollSeq *pColl = 0; struct ExprList_item *pItem; int j; assert( pList!=0 ); /* pList!=0 if pF->pFunc->needCollSeq is true */ for(j=0, pItem=pList->a; !pColl && j<nArg; j++, pItem++){ |
︙ | ︙ |
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.663 2008/01/02 14:28:13 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include "vdbeInt.h" /* ** The following global variable is incremented every time a cursor |
︙ | ︙ | |||
2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 | int nHdr = 0; /* Number of bytes of header space */ u64 nByte = 0; /* Data space required for this record */ int nZero = 0; /* Number of zero bytes at the end of the record */ int nVarint; /* Number of bytes in a varint */ u32 serial_type; /* Type field */ int containsNull = 0; /* True if any of the data fields are NULL */ Mem *pData0; /* Bottom of the stack */ int leaveOnStack; /* If true, leave the entries on the stack */ int nField; /* Number of fields in the record */ int jumpIfNull; /* Jump here if non-zero and any entries are NULL. */ int addRowid; /* True to append a rowid column at the end */ char *zAffinity; /* The affinity string for the record */ int file_format; /* File format to use for encoding */ int i; /* Space used in zNewRecord[] */ | > | 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 | int nHdr = 0; /* Number of bytes of header space */ u64 nByte = 0; /* Data space required for this record */ int nZero = 0; /* Number of zero bytes at the end of the record */ int nVarint; /* Number of bytes in a varint */ u32 serial_type; /* Type field */ int containsNull = 0; /* True if any of the data fields are NULL */ Mem *pData0; /* Bottom of the stack */ Mem *pLast; /* Top of the stack */ int leaveOnStack; /* If true, leave the entries on the stack */ int nField; /* Number of fields in the record */ int jumpIfNull; /* Jump here if non-zero and any entries are NULL. */ int addRowid; /* True to append a rowid column at the end */ char *zAffinity; /* The affinity string for the record */ int file_format; /* File format to use for encoding */ int i; /* Space used in zNewRecord[] */ |
︙ | ︙ | |||
2407 2408 2409 2410 2411 2412 2413 | if( pOp->opcode==OP_RegMakeRec || pOp->opcode==OP_RegMakeIRec ){ Mem *pCount; assert( nField>=0 && nField<p->nMem ); pCount = &p->aMem[nField]; assert( pCount->flags & MEM_Int ); assert( pCount->u.i>=0 && pCount->u.i+nField<p->nMem ); | | > > | | 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 | if( pOp->opcode==OP_RegMakeRec || pOp->opcode==OP_RegMakeIRec ){ Mem *pCount; assert( nField>=0 && nField<p->nMem ); pCount = &p->aMem[nField]; assert( pCount->flags & MEM_Int ); assert( pCount->u.i>=0 && pCount->u.i+nField<p->nMem ); leaveOnStack = 1; nField = pCount->u.i; pData0 = &pCount[1]; pLast = &pData0[nField-1]; }else{ pData0 = &pTos[1-nField]; pLast = pTos; assert( pData0>=p->aStack ); } containsNull = 0; file_format = p->minWriteFileFormat; /* Loop through the elements that will make up the record to figure ** out how much space is required for the new record. */ for(pRec=pData0; pRec<=pLast; pRec++){ int len; if( zAffinity ){ applyAffinity(pRec, zAffinity[pRec-pData0], encoding); } if( pRec->flags&MEM_Null ){ containsNull = 1; } |
︙ | ︙ | |||
2480 2481 2482 2483 2484 2485 2486 | } }else{ zNewRecord = (u8*)zTemp; } /* Write the record */ i = sqlite3PutVarint(zNewRecord, nHdr); | | | | 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 | } }else{ zNewRecord = (u8*)zTemp; } /* Write the record */ i = sqlite3PutVarint(zNewRecord, nHdr); for(pRec=pData0; pRec<=pLast; pRec++){ serial_type = sqlite3VdbeSerialType(pRec, file_format); i += sqlite3PutVarint(&zNewRecord[i], serial_type); /* serial type */ } if( addRowid ){ i += sqlite3PutVarint(&zNewRecord[i], sqlite3VdbeSerialType(pRowid, 0)); } for(pRec=pData0; pRec<=pLast; pRec++){ /* serial data */ i += sqlite3VdbeSerialPut(&zNewRecord[i], nByte-i, pRec, file_format); } if( addRowid ){ i += sqlite3VdbeSerialPut(&zNewRecord[i], nByte-i, pRowid, 0); } assert( i==nByte ); |
︙ | ︙ | |||
4715 4716 4717 4718 4719 4720 4721 | assert( pMem->flags==MEM_Int ); if( pMem->u.i==0 ){ pc = pOp->p2 - 1; } break; } | > > > > > > > > > > > > > | | | | | 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 | assert( pMem->flags==MEM_Int ); if( pMem->u.i==0 ){ pc = pOp->p2 - 1; } break; } /* Opcode: IfMemNull P1 P2 * ** ** If the value of memory cell P1 is NULL, jump to P2. */ case OP_IfMemNull: { /* no-push */ int i = pOp->p1; assert( i>=0 && i<p->nMem ); if( p->aMem[i].flags & MEM_Null ){ pc = pOp->p2 - 1; } break; } /* Opcode: MemNull * P2 * ** ** Store a NULL in memory cell P2 */ case OP_MemNull: { assert( pOp->p2>=0 && pOp->p2<p->nMem ); sqlite3VdbeMemSetNull(&p->aMem[pOp->p2]); break; } /* Opcode: MemInt P1 P2 * ** ** Store the integer value P1 in memory cell P2. */ |
︙ | ︙ |