Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -1228,19 +1228,20 @@ addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); VdbeCoverage(v); codeOffset(v, p->iOffset, addrContinue); sqlite3VdbeAddOp3(v, OP_SorterData, iTab, regSortOut, iSortTab); bSeq = 0; + sqlite3VdbeAddOp4Int(v, OP_Unpack, regSortOut, regRow, nSortData, nKey); }else{ addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v); codeOffset(v, p->iOffset, addrContinue); iSortTab = iTab; bSeq = 1; - } - for(i=0; inExpr; j++){ - if( groupBySort ){ - sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j); - }else{ + sqlite3VdbeAddOp4Int(v, OP_Unpack, sortOut, iBMem, pGroupBy->nExpr, 0); + }else{ + for(j=0; jnExpr; j++){ sAggInfo.directMode = 1; sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j); } } sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr, Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -2611,10 +2611,55 @@ op_column_error: UPDATE_MAX_BLOBSIZE(pDest); REGISTER_TRACE(pOp->p3, pDest); break; } + +/* Opcode: Unpack P1 P2 P3 P4 * +** Synopsis: r[P2@P3] = unpack(P1) +** +** Decode the P3 fields of the record object held in register P1 +** start with the P4-th field and store the values in registers P2 +** and following. +*/ +case OP_Unpack: { + const unsigned char *aKey; + int d; + u32 idx; /* Offset in aKey[] to read from */ + u16 u; /* Unsigned loop counter */ + u32 szHdr; + int nField; + u32 serial_type; + int iOfst; /* Skip this many fields */ + + pIn1 = &aMem[pOp->p1]; + assert( pIn1->flags & MEM_Blob ); + aKey = (const unsigned char*)pIn1->z; + pOut = &aMem[pOp->p2]; + nField = pOp->p3; + assert( pOp->p4type==P4_INT32 ); + iOfst = pOp->p4.i; + idx = getVarint32(aKey, szHdr); + d = szHdr; + u = 0; + while( idxn ){ + idx += getVarint32(&aKey[idx], serial_type); + if( iOfst ){ + iOfst--; + d += sqlite3VdbeSerialTypeLen(serial_type); + }else{ + memAboutToChange(p, pOut); + sqlite3VdbeMemSetNull(pOut); + pOut->enc = encoding; + d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pOut); + REGISTER_TRACE((int)(pOut - aMem), pOut); + pOut++; + if( (++u)>=nField ) break; + } + } + break; +} /* Opcode: Affinity P1 P2 * P4 * ** Synopsis: affinity(r[P1@P2]) ** ** Apply affinities to a range of P2 registers starting with P1.