Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Use a new opcode, OP_OpenHash, to indicate that ephemeral tables can be unordered, rather than using the BTREE_UNORDERED bit in the P5 field. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | subquery-codegen-refactor |
Files: | files | file ages | folders |
SHA1: |
2997e181575da7e37fe70d20bdddf934 |
User & Date: | drh 2014-02-05 18:15:38.286 |
Context
2014-02-05
| ||
19:10 | Separate out the code generators for the RHS of an IN operator and for SELECT/EXISTS expressions. (check-in: 61c34ba71b user: drh tags: subquery-codegen-refactor) | |
18:15 | Use a new opcode, OP_OpenHash, to indicate that ephemeral tables can be unordered, rather than using the BTREE_UNORDERED bit in the P5 field. (check-in: 2997e18157 user: drh tags: subquery-codegen-refactor) | |
17:08 | Make the root page of an ephemeral index be page 1 instead of page 2. (check-in: a332908b70 user: drh tags: subquery-codegen-refactor) | |
Changes
Changes to src/select.c.
︙ | ︙ | |||
2003 2004 2005 2006 2007 2008 2009 | v = sqlite3GetVdbe(pParse); assert( v!=0 ); /* The VDBE already created by calling function */ /* Create the destination temporary table if necessary */ if( dest.eDest==SRT_EphemTab ){ assert( p->pEList ); | | < | 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 | v = sqlite3GetVdbe(pParse); assert( v!=0 ); /* The VDBE already created by calling function */ /* Create the destination temporary table if necessary */ if( dest.eDest==SRT_EphemTab ){ assert( p->pEList ); sqlite3VdbeAddOp2(v, OP_OpenHash, dest.iSDParm, p->pEList->nExpr); dest.eDest = SRT_Table; } /* Make sure all SELECTs in the statement have the same number of elements ** in their result sets. */ assert( p->pEList && pPrior->pEList ); |
︙ | ︙ | |||
4736 4737 4738 4739 4740 4741 4742 | p->selFlags |= SF_UseSorter; } /* Open a virtual index to use for the distinct set. */ if( p->selFlags & SF_Distinct ){ sDistinct.tabTnct = pParse->nTab++; | | < | 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 | p->selFlags |= SF_UseSorter; } /* Open a virtual index to use for the distinct set. */ if( p->selFlags & SF_Distinct ){ sDistinct.tabTnct = pParse->nTab++; sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenHash, sDistinct.tabTnct, 0, 0, (char*)keyInfoFromExprList(pParse, p->pEList, 0), P4_KEYINFO); sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED; }else{ sDistinct.eTnctType = WHERE_DISTINCT_NOOP; } if( !isAgg && pGroupBy==0 ){ /* No aggregate functions and no GROUP BY clause */ |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
731 732 733 734 735 736 737 | pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0); /* Create the ephemeral table into which the update results will ** be stored. */ assert( v ); ephemTab = pParse->nTab++; | | < | 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 | pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0); /* Create the ephemeral table into which the update results will ** be stored. */ assert( v ); ephemTab = pParse->nTab++; sqlite3VdbeAddOp2(v, OP_OpenHash, ephemTab, pTab->nCol+1+(pRowid!=0)); /* fill the ephemeral table */ sqlite3SelectDestInit(&dest, SRT_Table, ephemTab); sqlite3Select(pParse, pSelect, &dest); /* Generate code to scan the ephemeral table and call VUpdate. */ |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
3291 3292 3293 3294 3295 3296 3297 | ** SQLite used to check if the root-page flags were sane at this point ** and report database corruption if they were not, but this check has ** since moved into the btree layer. */ pCur->isTable = pOp->p4type!=P4_KEYINFO; break; } | | > > > > > | < < > | > > > > > | > > > > > > | > > > > > > > > < < < < < | 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 | ** SQLite used to check if the root-page flags were sane at this point ** and report database corruption if they were not, but this check has ** since moved into the btree layer. */ pCur->isTable = pOp->p4type!=P4_KEYINFO; break; } /* Opcode: OpenEphemeral P1 P2 * P4 * ** Synopsis: nColumn=P2 ** ** Open a new cursor P1 to a transient table. ** The cursor is always opened read/write even if ** the main database is read-only. The ephemeral ** table is deleted automatically when the cursor is closed. ** ** P2 is the number of columns in the ephemeral table. ** The cursor points to a BTree table if P4==0 and to a BTree index ** if P4 is not 0. If P4 is not NULL, it points to a KeyInfo structure ** that defines the format of keys in the index. */ /* Opcode: OpenHash P1 P2 * P4 * ** Synopsis: nColumn=P2 ** ** Open a new cursor P1 to a transient table. ** P2 is the number of columns in the ephemeral table. ** The cursor points to a BTree table if P4==0 and to a BTree index ** if P4 is a KeyInfo structure. ** ** This opcode is identical to OP_OpenEphemeral except that it ** adds the BTREE_UNORDERED parameter to the sqlite3BtreeOpen() call, ** thus causing the underlying table to unordered. */ /* Opcode: OpenAutoindex P1 P2 * P4 * ** Synopsis: nColumn=P2 ** ** This opcode works the same as OP_OpenEphemeral. It has a ** different name to distinguish its use. Tables created using ** by this opcode will be used for automatically created transient ** indices in joins. */ case OP_OpenAutoindex: case OP_OpenHash: case OP_OpenEphemeral: { VdbeCursor *pCx; int btreeFlags; static const int vfsFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_TRANSIENT_DB; assert( pOp->p1>=0 ); assert( pOp->p2>=0 ); assert( pOp->p5==0 ); pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; btreeFlags = BTREE_OMIT_JOURNAL | BTREE_SINGLE; if( pOp->opcode==OP_OpenHash ){ btreeFlags |= BTREE_UNORDERED; pCx->isOrdered = 0; }else{ pCx->isOrdered = 1; } if( pOp->p4.pKeyInfo ){ assert( pOp->p4type==P4_KEYINFO ); assert( pOp->p4.pKeyInfo->db==db ); assert( pOp->p4.pKeyInfo->enc==ENC(db) ); btreeFlags |= BTREE_SINGLE_INDEX; pCx->isTable = 0; }else{ pCx->isTable = 1; } rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt, btreeFlags, vfsFlags); if( rc==SQLITE_OK ){ rc = sqlite3BtreeBeginTrans(pCx->pBt, 1); } if( rc==SQLITE_OK ){ rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, pOp->p4.pKeyInfo, pCx->pCursor); } pCx->pKeyInfo = pOp->p4.pKeyInfo; break; } /* Opcode: SorterOpen P1 * * P4 * ** ** This opcode works like OP_OpenEphemeral except that it opens ** a transient index that is specifically designed to sort large |
︙ | ︙ |
Changes to test/distinct.test.
︙ | ︙ | |||
47 48 49 50 51 52 53 | } proc do_temptables_test {tn sql temptables} { uplevel [list do_test $tn [subst -novar { set ret "" db eval "EXPLAIN [set sql]" { if {$opcode == "OpenEphemeral" || $opcode == "SorterOpen"} { | < < | | | < | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | } proc do_temptables_test {tn sql temptables} { uplevel [list do_test $tn [subst -novar { set ret "" db eval "EXPLAIN [set sql]" { if {$opcode == "OpenEphemeral" || $opcode == "SorterOpen"} { lappend ret btree } elseif {$opcode == "OpenHash"} { lappend ret hash } } set ret }] $temptables] } |
︙ | ︙ |