Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Make sure registers are cleared properly prior to being used to store the result of an OP_Column operator. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | micro-optimizations |
Files: | files | file ages | folders |
SHA1: |
78fb8838d80b229418c347c635799894 |
User & Date: | drh 2014-09-16 20:05:21.909 |
Context
2014-09-16
| ||
21:54 | Continuing cleanup of memory register memory allocation handling. (check-in: 2598aedc5d user: drh tags: micro-optimizations) | |
20:05 | Make sure registers are cleared properly prior to being used to store the result of an OP_Column operator. (check-in: 78fb8838d8 user: drh tags: micro-optimizations) | |
18:22 | Simplification of the OP_Column logic for the case of rows with overflow. (check-in: f73678038d user: drh tags: micro-optimizations) | |
Changes
Changes to src/vdbe.c.
︙ | ︙ | |||
2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 | /* Extract the content for the p2+1-th column. Control can only ** reach this point if aOffset[p2], aOffset[p2+1], and aType[p2] are ** all valid. */ assert( p2<pC->nHdrParsed ); assert( rc==SQLITE_OK ); assert( sqlite3VdbeCheckMemInvariants(pDest) ); if( pC->szRow>=aOffset[p2+1] ){ /* This is the common case where the desired content fits on the original ** page - where the content is not on an overflow page */ | > < | 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 | /* Extract the content for the p2+1-th column. Control can only ** reach this point if aOffset[p2], aOffset[p2+1], and aType[p2] are ** all valid. */ assert( p2<pC->nHdrParsed ); assert( rc==SQLITE_OK ); assert( sqlite3VdbeCheckMemInvariants(pDest) ); VdbeMemReleaseExtern(pDest); if( pC->szRow>=aOffset[p2+1] ){ /* This is the common case where the desired content fits on the original ** page - where the content is not on an overflow page */ sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], aType[p2], pDest); }else{ /* This branch happens only when content is on overflow pages */ t = aType[p2]; if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0 && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)) || (len = sqlite3VdbeSerialTypeLen(t))==0 |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 | const void *v1, *v2; int n1, n2; Mem c1; Mem c2; c1.db = c2.db = pMem1->db; c1.flags = c2.flags = 0; c1.zMalloc = c2.zMalloc = 0; sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem); sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem); v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc); n1 = v1==0 ? 0 : c1.n; v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc); n2 = v2==0 ? 0 : c2.n; rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2); | > | 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 | const void *v1, *v2; int n1, n2; Mem c1; Mem c2; c1.db = c2.db = pMem1->db; c1.flags = c2.flags = 0; c1.zMalloc = c2.zMalloc = 0; c1.xDel = c2.xDel = 0; sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem); sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem); v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc); n1 = v1==0 ? 0 : c1.n; v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc); n2 = v2==0 ? 0 : c2.n; rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2); |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
306 307 308 309 310 311 312 | memcpy(pMem, &t, sizeof(t)); rc = ctx.isError; } return rc; } /* | | | > > > | > | 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 | memcpy(pMem, &t, sizeof(t)); rc = ctx.isError; } return rc; } /* ** If the memory cell contains a value that must be freed by ** invoking an external callback, then free it now. ** ** This routine does NOT do any of the following: ** (1) Set the Mem.flags field to a rational value. ** (2) Free memory held by Mem.zMalloc ** The caller is expected to take care of setting Mem.flags appropriately. ** ** The VdbeMemReleaseExtern() macro invokes this routine if only if there ** is work for this routine to do. */ void sqlite3VdbeMemReleaseExternal(Mem *p){ assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) ); if( p->flags&MEM_Agg ){ |
︙ | ︙ | |||
336 337 338 339 340 341 342 | } /* ** Release memory held by the Mem p, both external memory cleared ** by p->xDel and memory in p->zMalloc. ** ** This is a helper routine invoked by sqlite3VdbeMemRelease() in | | | | | | > > | 340 341 342 343 344 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 | } /* ** Release memory held by the Mem p, both external memory cleared ** by p->xDel and memory in p->zMalloc. ** ** This is a helper routine invoked by sqlite3VdbeMemRelease() in ** the uncommon case when there really is memory in p that needs ** to be freeing. */ static SQLITE_NOINLINE void vdbeMemRelease(Mem *p){ if( VdbeMemDynamic(p) ){ sqlite3VdbeMemReleaseExternal(p); } if( p->zMalloc ){ sqlite3DbFree(p->db, p->zMalloc); p->zMalloc = 0; } p->z = 0; } /* ** Release any memory held by the Mem. This may leave the Mem.flags in an ** inconsistent state, for example with (Mem.z==0) and (Mem.flags==MEM_Str). ** ** This routine releases both the Mem.xDel space and the Mem.zMalloc space. ** Use sqlite3VdbeMemReleaseExternal() to release just the Mem.xDel space. */ void sqlite3VdbeMemRelease(Mem *p){ assert( sqlite3VdbeCheckMemInvariants(p) ); if( VdbeMemDynamic(p) || p->zMalloc ){ vdbeMemRelease(p); }else{ p->z = 0; |
︙ | ︙ | |||
729 730 731 732 733 734 735 | ** and flags gets srcType (either MEM_Ephem or MEM_Static). */ void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ assert( (pFrom->flags & MEM_RowSet)==0 ); assert( pTo->db==pFrom->db ); VdbeMemReleaseExtern(pTo); memcpy(pTo, pFrom, MEMCELLSIZE); | | | | 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 | ** and flags gets srcType (either MEM_Ephem or MEM_Static). */ void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ assert( (pFrom->flags & MEM_RowSet)==0 ); assert( pTo->db==pFrom->db ); VdbeMemReleaseExtern(pTo); memcpy(pTo, pFrom, MEMCELLSIZE); assert( pTo->xDel==0 ); if( (pFrom->flags&MEM_Static)==0 ){ pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem); assert( srcType==MEM_Ephem || srcType==MEM_Static ); pTo->flags |= srcType; } } /* ** Make a full copy of pFrom into pTo. Prior contents of pTo are ** freed before the copy is made. */ int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ int rc = SQLITE_OK; assert( pTo->db==pFrom->db ); assert( (pFrom->flags & MEM_RowSet)==0 ); VdbeMemReleaseExtern(pTo); memcpy(pTo, pFrom, MEMCELLSIZE); pTo->flags &= ~MEM_Dyn; assert( pTo->xDel==0 ); if( pTo->flags&(MEM_Str|MEM_Blob) ){ if( 0==(pFrom->flags&MEM_Static) ){ pTo->flags |= MEM_Ephem; rc = sqlite3VdbeMemMakeWriteable(pTo); } } |
︙ | ︙ | |||
902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 | Mem *pMem /* OUT: Return data in this Mem structure. */ ){ char *zData; /* Data from the btree layer */ u32 available = 0; /* Number of bytes available on the local btree page */ int rc = SQLITE_OK; /* Return code */ assert( sqlite3BtreeCursorIsValid(pCur) ); /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() ** that both the BtShared and database handle mutexes are held. */ assert( (pMem->flags & MEM_RowSet)==0 ); if( key ){ zData = (char *)sqlite3BtreeKeyFetch(pCur, &available); }else{ zData = (char *)sqlite3BtreeDataFetch(pCur, &available); } assert( zData!=0 ); if( offset+amt<=available ){ sqlite3VdbeMemRelease(pMem); pMem->z = &zData[offset]; pMem->flags = MEM_Blob|MEM_Ephem; pMem->n = (int)amt; | > > > | | | | | | | | | | | | | > | 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 | Mem *pMem /* OUT: Return data in this Mem structure. */ ){ char *zData; /* Data from the btree layer */ u32 available = 0; /* Number of bytes available on the local btree page */ int rc = SQLITE_OK; /* Return code */ assert( sqlite3BtreeCursorIsValid(pCur) ); assert( pMem->xDel==0 ); /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() ** that both the BtShared and database handle mutexes are held. */ assert( (pMem->flags & MEM_RowSet)==0 ); if( key ){ zData = (char *)sqlite3BtreeKeyFetch(pCur, &available); }else{ zData = (char *)sqlite3BtreeDataFetch(pCur, &available); } assert( zData!=0 ); if( offset+amt<=available ){ sqlite3VdbeMemRelease(pMem); pMem->z = &zData[offset]; pMem->flags = MEM_Blob|MEM_Ephem; pMem->n = (int)amt; }else{ pMem->flags = MEM_Null; if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){ if( key ){ rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z); }else{ rc = sqlite3BtreeData(pCur, offset, amt, pMem->z); } if( rc==SQLITE_OK ){ pMem->z[amt] = 0; pMem->z[amt+1] = 0; pMem->flags = MEM_Blob|MEM_Term; pMem->n = (int)amt; }else{ sqlite3VdbeMemRelease(pMem); } } } return rc; } /* |
︙ | ︙ |