Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add the OP_Undef and OP_IsUndef opcodes. With these, use the first register in the result register range as the flag to indicate EOF on an INSERT from a SELECT, rather than allocating a separate boolean register for that task. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | coroutine-refactor |
Files: | files | file ages | folders |
SHA1: |
6fb7448550f28a3c93053e125faeaf11 |
User & Date: | drh 2014-02-07 13:20:31.855 |
Context
2014-02-07
| ||
18:27 | Get rid of the OP_Undef and OP_IsUndef opcodes in favor of higher-level OP_InitCoroutine and OP_EndCoroutine. (check-in: 1ec0e9dd4b user: drh tags: coroutine-refactor) | |
13:20 | Add the OP_Undef and OP_IsUndef opcodes. With these, use the first register in the result register range as the flag to indicate EOF on an INSERT from a SELECT, rather than allocating a separate boolean register for that task. (check-in: 6fb7448550 user: drh tags: coroutine-refactor) | |
03:28 | More comment updates. No changes to code. (check-in: be24fbc221 user: mistachkin tags: trunk) | |
Changes
Changes to src/insert.c.
︙ | |||
345 346 347 348 349 350 351 | 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 | - - - - - - - + + + - - + - + - - - + - - - - + + | ** ** Registers are allocated as follows: ** ** pDest->iSDParm The register holding the next entry-point of the ** co-routine. Run the co-routine to its next breakpoint ** by calling "OP_Yield $X" where $X is pDest->iSDParm. ** |
︙ | |||
484 485 486 487 488 489 490 | 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 | - - + - + - - + - + | ** close cursors ** end foreach ** ** The 3rd template is for when the second template does not apply ** and the SELECT clause does not read from <table> at any time. ** The generated code follows this template: ** |
︙ | |||
572 573 574 575 576 577 578 | 561 562 563 564 565 566 567 568 569 570 571 572 573 574 | - | /* Register allocations */ int regFromSelect = 0;/* Base register for data coming from SELECT */ int regAutoinc = 0; /* Register holding the AUTOINCREMENT counter */ int regRowCount = 0; /* Memory cell used for the row counter */ int regIns; /* Block of regs holding rowid+data being inserted */ int regRowid; /* registers holding insert rowid */ int regData; /* register holding first column to insert */ |
︙ | |||
685 686 687 688 689 690 691 | 673 674 675 676 677 678 679 680 681 682 683 684 685 686 | - | ** co-routine is the common header to the 3rd and 4th templates. */ if( pSelect ){ /* Data is coming from a SELECT. Generate a co-routine to run the SELECT */ int rc = sqlite3CodeCoroutine(pParse, pSelect, &dest); if( rc ) goto insert_cleanup; |
︙ | |||
711 712 713 714 715 716 717 | 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 | - + - + | if( useTempTable ){ /* Invoke the coroutine to extract information from the SELECT ** and add it to a transient table srcTab. The code generated ** here is from the 4th template: ** ** B: open temp table ** L: yield X |
︙ | |||
856 857 858 859 860 861 862 | 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 | - + - + | addrInsTop = sqlite3VdbeAddOp1(v, OP_Rewind, srcTab); addrCont = sqlite3VdbeCurrentAddr(v); }else if( pSelect ){ /* This block codes the top of loop only. The complete loop is the ** following pseudocode (template 3): ** ** C: yield X |
︙ |
Changes to src/vdbe.c.
︙ | |||
389 390 391 392 393 394 395 | 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 | - + | #endif #ifdef SQLITE_DEBUG /* ** Print the value of a register for tracing purposes: */ static void memTracePrint(Mem *p){ |
︙ | |||
698 699 700 701 702 703 704 | 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 | - - - | } #endif break; } /* Opcode: Gosub P1 P2 * * * |
︙ | |||
970 971 972 973 974 975 976 | 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 | - + + + + + + + + + + + + + + + + | pOut->flags = nullFlag; cnt--; } break; } |
︙ | |||
2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 | 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 | + + + + + + + + + + + + + | if( pOp->opcode==OP_IfNot ) c = !c; } if( c ){ pc = pOp->p2-1; } break; } /* Opcode: IsUndef P1 P2 * * * ** Synopsis: if r[P1]==undefined goto P2 ** ** Jump to P2 if the value in register P1 is undefined */ case OP_IsUndef: { /* jump */ pIn1 = &aMem[pOp->p1]; if( (pIn1->flags & MEM_Undefined)!=0 ){ pc = pOp->p2 - 1; } break; } /* Opcode: IsNull P1 P2 * * * ** Synopsis: if r[P1]==NULL goto P2 ** ** Jump to P2 if the value in register P1 is NULL. */ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ |
︙ | |||
5187 5188 5189 5190 5191 5192 5193 | 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 | - + | pFrame->nOp = p->nOp; pFrame->token = pProgram->token; pFrame->aOnceFlag = p->aOnceFlag; pFrame->nOnceFlag = p->nOnceFlag; pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem]; for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){ |
︙ |
Changes to src/vdbeInt.h.
︙ | |||
194 195 196 197 198 199 200 | 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | - + | #define MEM_Null 0x0001 /* Value is NULL */ #define MEM_Str 0x0002 /* Value is a string */ #define MEM_Int 0x0004 /* Value is an integer */ #define MEM_Real 0x0008 /* Value is a real number */ #define MEM_Blob 0x0010 /* Value is a BLOB */ #define MEM_RowSet 0x0020 /* Value is a RowSet object */ #define MEM_Frame 0x0040 /* Value is a VdbeFrame object */ |
︙ | |||
226 227 228 229 230 231 232 | 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | - + | ((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero))|f) /* ** Return true if a memory cell is not marked as invalid. This macro ** is for use inside assert() statements only. */ #ifdef SQLITE_DEBUG |
︙ |
Changes to src/vdbeaux.c.
︙ | |||
1230 1231 1232 1233 1234 1235 1236 | 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 | - + | if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){ sqlite3VdbeMemRelease(p); }else if( p->zMalloc ){ sqlite3DbFree(db, p->zMalloc); p->zMalloc = 0; } |
︙ | |||
1698 1699 1700 1701 1702 1703 1704 | 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 | - + | memcpy(p->azVar, pParse->azVar, p->nzVar*sizeof(p->azVar[0])); memset(pParse->azVar, 0, pParse->nzVar*sizeof(pParse->azVar[0])); } if( p->aMem ){ p->aMem--; /* aMem[] goes from 1..nMem */ p->nMem = nMem; /* not from 0..nMem-1 */ for(n=1; n<=nMem; n++){ |
︙ | |||
1810 1811 1812 1813 1814 1815 1816 | 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 | - + | #ifdef SQLITE_DEBUG /* Execute assert() statements to ensure that the Vdbe.apCsr[] and ** Vdbe.aMem[] arrays have already been cleaned up. */ int i; if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 ); if( p->aMem ){ |
︙ |
Changes to src/vdbemem.c.
︙ | |||
583 584 585 586 587 588 589 | 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 | - + | ** copies are not misused. */ void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){ int i; Mem *pX; for(i=1, pX=&pVdbe->aMem[1]; i<=pVdbe->nMem; i++, pX++){ if( pX->pScopyFrom==pMem ){ |
︙ |