Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | When constructing records and index keys, use static string space rather than mallocing (when possible) for a small speed improvement. (CVS 817) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
657c9fb5133aef93e4edd433912e6942 |
User & Date: | drh 2003-01-07 13:43:46.000 |
Context
2003-01-07
| ||
13:55 | In the VDBE, allocate space to hold column names when the VDBE first starts. The ColumnCount opcode now just writes the null terminator into this space. (CVS 818) (check-in: 46d8f5e377 user: drh tags: trunk) | |
13:43 | When constructing records and index keys, use static string space rather than mallocing (when possible) for a small speed improvement. (CVS 817) (check-in: 657c9fb513 user: drh tags: trunk) | |
02:47 | More optimizations. (CVS 816) (check-in: a362981b20 user: drh tags: trunk) | |
Changes
Changes to src/vdbe.c.
︙ | ︙ | |||
32 33 34 35 36 37 38 | ** ** 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. ** | | | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | ** ** 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.193 2003/01/07 13:43:46 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** The makefile scans this source file and creates the following ** array of string constants which are the names of all VDBE opcodes. |
︙ | ︙ | |||
772 773 774 775 776 777 778 | pElem = sqliteHashFirst(&p->hash); } return pElem ? sqliteHashData(pElem) : 0; } /* ** Convert the given stack entity into a string if it isn't one | | < < | < | | > > > > > > > > > > > > > > > > > > > > > > > > | 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 | pElem = sqliteHashFirst(&p->hash); } return pElem ? sqliteHashData(pElem) : 0; } /* ** Convert the given stack entity into a string if it isn't one ** already. */ #define Stringify(P,I) if((aStack[I].flags & STK_Str)==0){hardStringify(P,I);} static int hardStringify(Vdbe *p, int i){ Stack *pStack = &p->aStack[i]; int fg = pStack->flags; if( fg & STK_Real ){ sprintf(pStack->z,"%.15g",pStack->r); }else if( fg & STK_Int ){ sprintf(pStack->z,"%d",pStack->i); }else{ pStack->z[0] = 0; } p->zStack[i] = pStack->z; pStack->n = strlen(pStack->z)+1; pStack->flags = STK_Str; return 0; } /* ** Convert the given stack entity into a string that has been obtained ** from sqliteMalloc(). This is different from Stringify() above in that ** Stringify() will use the NBFS bytes of static string space if the string ** will fit but this routine always mallocs for space. ** Return non-zero if we run out of memory. */ #define Dynamicify(P,I) ((aStack[I].flags & STK_Dyn)==0 ? hardDynamicify(P,I):0) static int hardDynamicify(Vdbe *p, int i){ Stack *pStack = &p->aStack[i]; int fg = pStack->flags; char *z; if( (fg & STK_Str)==0 ){ hardStringify(p, i); } assert( (fg & STK_Dyn)==0 ); z = sqliteMallocRaw( pStack->n ); if( z==0 ) return 1; memcpy(z, p->zStack[i], pStack->n); p->zStack[i] = z; pStack->flags |= STK_Dyn; return 0; } /* ** An ephemeral string value (signified by the STK_Ephem flag) contains ** a pointer to a dynamically allocated string where some other entity ** is responsible for deallocating that string. Because the stack entry ** does not control the string, it might be deleted without the stack ** entry knowing it. |
︙ | ︙ | |||
1736 1737 1738 1739 1740 1741 1742 | int i = p->tos - pOp->p1 + 1; int j; VERIFY( if( i<0 ) goto not_enough_stack; ) for(j=i; j<=p->tos; j++){ if( aStack[j].flags & STK_Null ){ zStack[j] = 0; }else{ | | | 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 | int i = p->tos - pOp->p1 + 1; int j; VERIFY( if( i<0 ) goto not_enough_stack; ) for(j=i; j<=p->tos; j++){ if( aStack[j].flags & STK_Null ){ zStack[j] = 0; }else{ Stringify(p, j); } } zStack[p->tos+1] = 0; if( xCallback!=0 ){ if( sqliteSafetyOff(db) ) goto abort_due_to_misuse; if( xCallback(pArg, pOp->p1, &zStack[i], p->azColName)!=0 ){ rc = SQLITE_ABORT; |
︙ | ︙ | |||
1813 1814 1815 1816 1817 1818 1819 | VERIFY( if( p->tos+1<nField ) goto not_enough_stack; ) nByte = 1 - nSep; for(i=p->tos-nField+1; i<=p->tos; i++){ if( aStack[i].flags & STK_Null ){ nByte = -1; break; }else{ | | | 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 | VERIFY( if( p->tos+1<nField ) goto not_enough_stack; ) nByte = 1 - nSep; for(i=p->tos-nField+1; i<=p->tos; i++){ if( aStack[i].flags & STK_Null ){ nByte = -1; break; }else{ Stringify(p, i); nByte += aStack[i].n - 1 + nSep; } } if( nByte<0 ){ if( pOp->p2==0 ) PopStack(p, nField); p->tos++; aStack[p->tos].flags = STK_Null; |
︙ | ︙ | |||
1983 1984 1985 1986 1987 1988 1989 | n = pOp->p1; VERIFY( if( n<0 ) goto bad_instruction; ) VERIFY( if( p->tos+1<n ) goto not_enough_stack; ) for(i=p->tos-n+1; i<=p->tos; i++){ if( aStack[i].flags & STK_Null ){ zStack[i] = 0; }else{ | | | 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 | n = pOp->p1; VERIFY( if( n<0 ) goto bad_instruction; ) VERIFY( if( p->tos+1<n ) goto not_enough_stack; ) for(i=p->tos-n+1; i<=p->tos; i++){ if( aStack[i].flags & STK_Null ){ zStack[i] = 0; }else{ Stringify(p, i); } } ctx.pFunc = (FuncDef*)pOp->p3; ctx.s.flags = STK_Null; ctx.z = 0; ctx.isError = 0; ctx.isStep = 0; |
︙ | ︙ | |||
2279 2280 2281 2282 2283 2284 2285 | c = aStack[nos].i - aStack[tos].i; }else if( (fn & STK_Int)!=0 && (ft & STK_Str)!=0 && toInt(zStack[tos],&v) ){ Release(p, tos); aStack[tos].i = v; aStack[tos].flags = STK_Int; c = aStack[nos].i - aStack[tos].i; }else{ | | > | 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 | c = aStack[nos].i - aStack[tos].i; }else if( (fn & STK_Int)!=0 && (ft & STK_Str)!=0 && toInt(zStack[tos],&v) ){ Release(p, tos); aStack[tos].i = v; aStack[tos].flags = STK_Int; c = aStack[nos].i - aStack[tos].i; }else{ Stringify(p, tos); Stringify(p, nos); c = sqliteCompare(zStack[nos], zStack[tos]); } switch( pOp->opcode ){ case OP_Eq: c = c==0; break; case OP_Ne: c = c!=0; break; case OP_Lt: c = c<0; break; case OP_Le: c = c<=0; break; |
︙ | ︙ | |||
2429 2430 2431 2432 2433 2434 2435 | if( pOp->p1 ) pc = pOp->p2-1; }else{ p->tos++; aStack[nos].flags = STK_Null; } break; }else{ | | > | 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 | if( pOp->p1 ) pc = pOp->p2-1; }else{ p->tos++; aStack[nos].flags = STK_Null; } break; }else{ Stringify(p, tos); Stringify(p, nos); c = strcmp(zStack[nos], zStack[tos]); } /* The asserts on each case of the following switch are there to verify ** that string comparison opcodes are always exactly 6 greater than the ** corresponding numeric comparison opcodes. The code generator depends ** on this fact. */ |
︙ | ︙ | |||
2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 | int nByte; int nField; int i, j; int idxWidth; u32 addr; int addUnique = 0; /* True to cause bytes to be added to make the ** generated record distinct */ /* Assuming the record contains N fields, the record format looks ** like this: ** ** ------------------------------------------------------------------- ** | idx0 | idx1 | ... | idx(N-1) | idx(N) | data0 | ... | data(N-1) | ** ------------------------------------------------------------------- | > | 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 | int nByte; int nField; int i, j; int idxWidth; u32 addr; int addUnique = 0; /* True to cause bytes to be added to make the ** generated record distinct */ char zTemp[NBFS]; /* Temp space for small records */ /* Assuming the record contains N fields, the record format looks ** like this: ** ** ------------------------------------------------------------------- ** | idx0 | idx1 | ... | idx(N-1) | idx(N) | data0 | ... | data(N-1) | ** ------------------------------------------------------------------- |
︙ | ︙ | |||
2716 2717 2718 2719 2720 2721 2722 | nField = pOp->p1; VERIFY( if( p->tos+1<nField ) goto not_enough_stack; ) nByte = 0; for(i=p->tos-nField+1; i<=p->tos; i++){ if( (aStack[i].flags & STK_Null) ){ addUnique = pOp->p2; }else{ | | > > > | | > | 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 | nField = pOp->p1; VERIFY( if( p->tos+1<nField ) goto not_enough_stack; ) nByte = 0; for(i=p->tos-nField+1; i<=p->tos; i++){ if( (aStack[i].flags & STK_Null) ){ addUnique = pOp->p2; }else{ Stringify(p, i); nByte += aStack[i].n; } } if( addUnique ) nByte += sizeof(uniqueCnt); if( nByte + nField + 1 < 256 ){ idxWidth = 1; }else if( nByte + 2*nField + 2 < 65536 ){ idxWidth = 2; }else{ idxWidth = 3; } nByte += idxWidth*(nField + 1); if( nByte>MAX_BYTES_PER_ROW ){ rc = SQLITE_TOOBIG; goto abort_due_to_error; } if( nByte<=NBFS ){ zNewRecord = zTemp; }else{ zNewRecord = sqliteMallocRaw( nByte ); if( zNewRecord==0 ) goto no_mem; } j = 0; addr = idxWidth*(nField+1) + addUnique*sizeof(uniqueCnt); for(i=p->tos-nField+1; i<=p->tos; i++){ zNewRecord[j++] = addr & 0xff; if( idxWidth>1 ){ zNewRecord[j++] = (addr>>8)&0xff; if( idxWidth>2 ){ |
︙ | ︙ | |||
2770 2771 2772 2773 2774 2775 2776 | memcpy(&zNewRecord[j], zStack[i], aStack[i].n); j += aStack[i].n; } } PopStack(p, nField); p->tos++; aStack[p->tos].n = nByte; | > > > > > > > | | > | 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 | memcpy(&zNewRecord[j], zStack[i], aStack[i].n); j += aStack[i].n; } } PopStack(p, nField); p->tos++; aStack[p->tos].n = nByte; if( nByte<=NBFS ){ assert( zNewRecord==zTemp ); memcpy(aStack[p->tos].z, zTemp, nByte); zStack[p->tos] = aStack[p->tos].z; aStack[p->tos].flags = STK_Str; }else{ assert( zNewRecord!=zTemp ); aStack[p->tos].flags = STK_Str | STK_Dyn; zStack[p->tos] = zNewRecord; } break; } /* Opcode: MakeKey P1 P2 P3 ** ** Convert the top P1 entries of the stack into a single entry suitable ** for use as the key in an index. The top P1 records are |
︙ | ︙ | |||
2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 | case OP_MakeKey: { char *zNewKey; int nByte; int nField; int addRowid; int i, j; int containsNull = 0; addRowid = pOp->opcode==OP_MakeIdxKey; nField = pOp->p1; VERIFY( if( p->tos+1+addRowid<nField ) goto not_enough_stack; ) nByte = 0; for(j=0, i=p->tos-nField+1; i<=p->tos; i++, j++){ int flags = aStack[i].flags; | > | 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 | case OP_MakeKey: { char *zNewKey; int nByte; int nField; int addRowid; int i, j; int containsNull = 0; char zTemp[NBFS]; addRowid = pOp->opcode==OP_MakeIdxKey; nField = pOp->p1; VERIFY( if( p->tos+1+addRowid<nField ) goto not_enough_stack; ) nByte = 0; for(j=0, i=p->tos-nField+1; i<=p->tos; i++, j++){ int flags = aStack[i].flags; |
︙ | ︙ | |||
2886 2887 2888 2889 2890 2891 2892 | } } if( nByte+sizeof(u32)>MAX_BYTES_PER_ROW ){ rc = SQLITE_TOOBIG; goto abort_due_to_error; } if( addRowid ) nByte += sizeof(u32); | > > > | | > | 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 | } } if( nByte+sizeof(u32)>MAX_BYTES_PER_ROW ){ rc = SQLITE_TOOBIG; goto abort_due_to_error; } if( addRowid ) nByte += sizeof(u32); if( nByte<=NBFS ){ zNewKey = zTemp; }else{ zNewKey = sqliteMallocRaw( nByte ); if( zNewKey==0 ) goto no_mem; } j = 0; for(i=p->tos-nField+1; i<=p->tos; i++){ if( aStack[i].flags & STK_Null ){ zNewKey[j++] = 'a'; zNewKey[j++] = 0; }else{ if( aStack[i].flags & (STK_Int|STK_Real) ){ |
︙ | ︙ | |||
2915 2916 2917 2918 2919 2920 2921 | PopStack(p, nField+1); if( pOp->p2 && containsNull ) pc = pOp->p2 - 1; }else{ if( pOp->p2==0 ) PopStack(p, nField+addRowid); } p->tos++; aStack[p->tos].n = nByte; | > > > > > > | | > | | 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 | PopStack(p, nField+1); if( pOp->p2 && containsNull ) pc = pOp->p2 - 1; }else{ if( pOp->p2==0 ) PopStack(p, nField+addRowid); } p->tos++; aStack[p->tos].n = nByte; if( nByte<=NBFS ){ assert( zNewKey==zTemp ); zStack[p->tos] = aStack[p->tos].z; memcpy(zStack[p->tos], zTemp, nByte); aStack[p->tos].flags = STK_Str; }else{ aStack[p->tos].flags = STK_Str|STK_Dyn; zStack[p->tos] = zNewKey; } break; } /* Opcode: IncrKey * * * ** ** The top of the stack should contain an index key generated by ** The MakeKey opcode. This routine increases the least significant ** byte of that key by one. This is used so that the MoveTo opcode ** will move to the first entry greater than the key rather than to ** the key itself. */ case OP_IncrKey: { int tos = p->tos; VERIFY( if( tos<0 ) goto bad_instruction ); Stringify(p, tos); if( aStack[tos].flags & (STK_Static|STK_Ephem) ){ /* CANT HAPPEN. The IncrKey opcode is only applied to keys ** generated by MakeKey or MakeIdxKey and the results of those ** operands are always dynamic strings. */ goto abort_due_to_error; } |
︙ | ︙ | |||
3360 3361 3362 3363 3364 3365 3366 | int res, oc; if( aStack[tos].flags & STK_Int ){ int iKey = intToKey(aStack[tos].i); sqliteBtreeMoveto(pC->pCursor, (char*)&iKey, sizeof(int), &res); pC->lastRecno = aStack[tos].i; pC->recnoIsValid = res==0; }else{ | | | 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 | int res, oc; if( aStack[tos].flags & STK_Int ){ int iKey = intToKey(aStack[tos].i); sqliteBtreeMoveto(pC->pCursor, (char*)&iKey, sizeof(int), &res); pC->lastRecno = aStack[tos].i; pC->recnoIsValid = res==0; }else{ Stringify(p, tos); sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res); pC->recnoIsValid = 0; } pC->nullRow = 0; sqlite_search_count++; oc = pOp->opcode; if( oc==OP_MoveTo && res<0 ){ |
︙ | ︙ | |||
3436 3437 3438 3439 3440 3441 3442 | int i = pOp->p1; int tos = p->tos; int alreadyExists = 0; Cursor *pC; VERIFY( if( tos<0 ) goto not_enough_stack; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){ int res, rx; | | | 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 | int i = pOp->p1; int tos = p->tos; int alreadyExists = 0; Cursor *pC; VERIFY( if( tos<0 ) goto not_enough_stack; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){ int res, rx; Stringify(p, tos); rx = sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res); alreadyExists = rx==SQLITE_OK && res==0; } if( pOp->opcode==OP_Found ){ if( alreadyExists ) pc = pOp->p2 - 1; }else{ if( !alreadyExists ) pc = pOp->p2 - 1; |
︙ | ︙ | |||
3492 3493 3494 3495 3496 3497 3498 | int res, rc; int v; /* The record number on the P1 entry that matches K */ char *zKey; /* The value of K */ int nKey; /* Number of bytes in K */ /* Make sure K is a string and make zKey point to K */ | | | 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 | int res, rc; int v; /* The record number on the P1 entry that matches K */ char *zKey; /* The value of K */ int nKey; /* Number of bytes in K */ /* Make sure K is a string and make zKey point to K */ Stringify(p, nos); zKey = zStack[nos]; nKey = aStack[nos].n; assert( nKey >= 4 ); /* Search for an entry in P1 where all but the last four bytes match K. ** If there is no such entry, jump immediately to P2. */ |
︙ | ︙ | |||
3705 3706 3707 3708 3709 3710 3711 | int i = pOp->p1; Cursor *pC; VERIFY( if( nos<0 ) goto not_enough_stack; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){ char *zKey; int nKey, iKey; if( pOp->opcode==OP_PutStrKey ){ | | | 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 | int i = pOp->p1; Cursor *pC; VERIFY( if( nos<0 ) goto not_enough_stack; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){ char *zKey; int nKey, iKey; if( pOp->opcode==OP_PutStrKey ){ Stringify(p, nos); nKey = aStack[nos].n; zKey = zStack[nos]; }else{ assert( aStack[nos].flags & STK_Int ); nKey = sizeof(int); iKey = intToKey(aStack[nos].i); zKey = (char*)&iKey; |
︙ | ︙ | |||
4195 4196 4197 4198 4199 4200 4201 | int i= pOp->p1; int tos = p->tos; BtCursor *pCrsr; if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ int res, rc; | | | 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 | int i= pOp->p1; int tos = p->tos; BtCursor *pCrsr; if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ int res, rc; Stringify(p, tos); rc = sqliteBtreeKeyCompare(pCrsr, zStack[tos], aStack[tos].n, 4, &res); if( rc!=SQLITE_OK ){ break; } if( pOp->opcode==OP_IdxLT ){ res = -res; }else if( pOp->opcode==OP_IdxGE ){ |
︙ | ︙ | |||
4458 4459 4460 4461 4462 4463 4464 | ** made using SortMakeKey and SortMakeRec, respectively. */ case OP_SortPut: { int tos = p->tos; int nos = tos - 1; Sorter *pSorter; VERIFY( if( tos<1 ) goto not_enough_stack; ) | | | 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 | ** made using SortMakeKey and SortMakeRec, respectively. */ case OP_SortPut: { int tos = p->tos; int nos = tos - 1; Sorter *pSorter; VERIFY( if( tos<1 ) goto not_enough_stack; ) if( Dynamicify(p, tos) || Dynamicify(p, nos) ) goto no_mem; pSorter = sqliteMallocRaw( sizeof(Sorter) ); if( pSorter==0 ) goto no_mem; pSorter->pNext = p->pSort; p->pSort = pSorter; assert( aStack[tos].flags & STK_Dyn ); pSorter->nKey = aStack[tos].n; pSorter->zKey = zStack[tos]; |
︙ | ︙ | |||
4498 4499 4500 4501 4502 4503 4504 | int i, j; nField = pOp->p1; VERIFY( if( p->tos+1<nField ) goto not_enough_stack; ) nByte = 0; for(i=p->tos-nField+1; i<=p->tos; i++){ if( (aStack[i].flags & STK_Null)==0 ){ | | | 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 | int i, j; nField = pOp->p1; VERIFY( if( p->tos+1<nField ) goto not_enough_stack; ) nByte = 0; for(i=p->tos-nField+1; i<=p->tos; i++){ if( (aStack[i].flags & STK_Null)==0 ){ Stringify(p, i); nByte += aStack[i].n; } } nByte += sizeof(char*)*(nField+1); azArg = sqliteMallocRaw( nByte ); if( azArg==0 ) goto no_mem; z = (char*)&azArg[nField+1]; |
︙ | ︙ | |||
4551 4552 4553 4554 4555 4556 4557 | nField = strlen(pOp->p3); VERIFY( if( p->tos+1<nField ) goto not_enough_stack; ) nByte = 1; for(i=p->tos-nField+1; i<=p->tos; i++){ if( (aStack[i].flags & STK_Null)!=0 ){ nByte += 2; }else{ | | | 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 | nField = strlen(pOp->p3); VERIFY( if( p->tos+1<nField ) goto not_enough_stack; ) nByte = 1; for(i=p->tos-nField+1; i<=p->tos; i++){ if( (aStack[i].flags & STK_Null)!=0 ){ nByte += 2; }else{ Stringify(p, i); nByte += aStack[i].n+2; } } zNewKey = sqliteMallocRaw( nByte ); if( zNewKey==0 ) goto no_mem; j = 0; k = 0; |
︙ | ︙ | |||
4995 4996 4997 4998 4999 5000 5001 | VERIFY( if( n<0 ) goto bad_instruction; ) VERIFY( if( p->tos+1<n ) goto not_enough_stack; ) VERIFY( if( aStack[p->tos].flags!=STK_Int ) goto bad_instruction; ) for(i=p->tos-n; i<p->tos; i++){ if( aStack[i].flags & STK_Null ){ zStack[i] = 0; }else{ | | | 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 | VERIFY( if( n<0 ) goto bad_instruction; ) VERIFY( if( p->tos+1<n ) goto not_enough_stack; ) VERIFY( if( aStack[p->tos].flags!=STK_Int ) goto bad_instruction; ) for(i=p->tos-n; i<p->tos; i++){ if( aStack[i].flags & STK_Null ){ zStack[i] = 0; }else{ Stringify(p, i); } } i = aStack[p->tos].i; VERIFY( if( i<0 || i>=p->agg.nMem ) goto bad_instruction; ) ctx.pFunc = (FuncDef*)pOp->p3; pMem = &p->agg.pCurrent->aMem[i]; ctx.z = pMem->s.z; |
︙ | ︙ | |||
5038 5039 5040 5041 5042 5043 5044 | case OP_AggFocus: { int tos = p->tos; AggElem *pElem; char *zKey; int nKey; VERIFY( if( tos<0 ) goto not_enough_stack; ) | | | 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 | case OP_AggFocus: { int tos = p->tos; AggElem *pElem; char *zKey; int nKey; VERIFY( if( tos<0 ) goto not_enough_stack; ) Stringify(p, tos); zKey = zStack[tos]; nKey = aStack[tos].n; pElem = sqliteHashFind(&p->agg.hash, zKey, nKey); if( pElem ){ p->agg.pCurrent = pElem; pc = pOp->p2 - 1; }else{ |
︙ | ︙ | |||
5188 5189 5190 5191 5192 5193 5194 | p->nSet = i+1; } if( pOp->p3 ){ sqliteHashInsert(&p->aSet[i].hash, pOp->p3, strlen(pOp->p3)+1, p); }else{ int tos = p->tos; if( tos<0 ) goto not_enough_stack; | | | | | 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 | p->nSet = i+1; } if( pOp->p3 ){ sqliteHashInsert(&p->aSet[i].hash, pOp->p3, strlen(pOp->p3)+1, p); }else{ int tos = p->tos; if( tos<0 ) goto not_enough_stack; Stringify(p, tos); sqliteHashInsert(&p->aSet[i].hash, zStack[tos], aStack[tos].n, p); POPSTACK; } if( sqlite_malloc_failed ) goto no_mem; break; } /* Opcode: SetFound P1 P2 * ** ** Pop the stack once and compare the value popped off with the ** contents of set P1. If the element popped exists in set P1, ** then jump to P2. Otherwise fall through. */ case OP_SetFound: { int i = pOp->p1; int tos = p->tos; VERIFY( if( tos<0 ) goto not_enough_stack; ) Stringify(p, tos); if( i>=0 && i<p->nSet && sqliteHashFind(&p->aSet[i].hash, zStack[tos], aStack[tos].n)){ pc = pOp->p2 - 1; } POPSTACK; break; } /* Opcode: SetNotFound P1 P2 * ** ** Pop the stack once and compare the value popped off with the ** contents of set P1. If the element popped does not exists in ** set P1, then jump to P2. Otherwise fall through. */ case OP_SetNotFound: { int i = pOp->p1; int tos = p->tos; VERIFY( if( tos<0 ) goto not_enough_stack; ) Stringify(p, tos); if( i<0 || i>=p->nSet || sqliteHashFind(&p->aSet[i].hash, zStack[tos], aStack[tos].n)==0 ){ pc = pOp->p2 - 1; } POPSTACK; break; } |
︙ | ︙ |