/ Check-in [f2f5a3ce]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Another simplification to the OP_MakeRecord opcode, making it slightly faster and very slightly smaller.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: f2f5a3ce9d075c4b1ac586c5db3a623d9035402d
User & Date: drh 2013-12-08 23:33:28
Context
2013-12-09
00:47
Use putVarint32() instead of putVarint() for a quantity that can never exceed 2GiB - 1. check-in: 6996fb34 user: drh tags: trunk
2013-12-08
23:33
Another simplification to the OP_MakeRecord opcode, making it slightly faster and very slightly smaller. check-in: f2f5a3ce user: drh tags: trunk
22:59
Avoid unnecessary calls to sqlite3VarintLen() from the OP_MakeRecord opcode. check-in: 7a234fc3 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

  2556   2556     int nVarint;           /* Number of bytes in a varint */
  2557   2557     u32 serial_type;       /* Type field */
  2558   2558     Mem *pData0;           /* First field to be combined into the record */
  2559   2559     Mem *pLast;            /* Last field of the record */
  2560   2560     int nField;            /* Number of fields in the record */
  2561   2561     char *zAffinity;       /* The affinity string for the record */
  2562   2562     int file_format;       /* File format to use for encoding */
  2563         -  int i;                 /* Space used in zNewRecord[] */
         2563  +  int i;                 /* Space used in zNewRecord[] header */
         2564  +  int j;                 /* Space used in zNewRecord[] content */
  2564   2565     int len;               /* Length of a field */
  2565   2566   
  2566   2567     /* Assuming the record contains N fields, the record format looks
  2567   2568     ** like this:
  2568   2569     **
  2569   2570     ** ------------------------------------------------------------------------
  2570   2571     ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 | 
................................................................................
  2593   2594     assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
  2594   2595     pOut = &aMem[pOp->p3];
  2595   2596     memAboutToChange(p, pOut);
  2596   2597   
  2597   2598     /* Loop through the elements that will make up the record to figure
  2598   2599     ** out how much space is required for the new record.
  2599   2600     */
  2600         -  for(pRec=pData0; pRec<=pLast; pRec++){
         2601  +  assert( pData0<=pLast );
         2602  +  pRec = pData0;
         2603  +  do{
  2601   2604       assert( memIsValid(pRec) );
  2602   2605       if( zAffinity ){
  2603   2606         applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
  2604   2607       }
  2605         -    if( pRec->flags&MEM_Zero && pRec->n>0 ){
         2608  +    if( (pRec->flags&MEM_Zero)!=0 && pRec->n>0 ){
  2606   2609         sqlite3VdbeMemExpandBlob(pRec);
  2607   2610       }
  2608   2611       serial_type = sqlite3VdbeSerialType(pRec, file_format);
  2609   2612       len = sqlite3VdbeSerialTypeLen(serial_type);
  2610   2613       nData += len;
         2614  +    testcase( serial_type==127 );
         2615  +    testcase( serial_type==128 );
  2611   2616       nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type);
  2612   2617       if( pRec->flags & MEM_Zero ){
  2613   2618         /* Only pure zero-filled BLOBs can be input to this Opcode.
  2614   2619         ** We do not allow blobs with a prefix and a zero-filled tail. */
  2615   2620         nZero += pRec->u.nZero;
  2616   2621       }else if( len ){
  2617   2622         nZero = 0;
  2618   2623       }
  2619         -  }
         2624  +  }while( (++pRec)<=pLast );
  2620   2625   
  2621   2626     /* Add the initial header varint and total the size */
         2627  +  testcase( nHdr==126 );
         2628  +  testcase( nHdr==127 );
  2622   2629     if( nHdr<=126 ){
  2623   2630       /* The common case */
  2624   2631       nHdr += 1;
  2625   2632     }else{
  2626   2633       /* Rare case of a really large header */
  2627   2634       nVarint = sqlite3VarintLen(nHdr);
  2628   2635       nHdr += nVarint;
................................................................................
  2641   2648     if( sqlite3VdbeMemGrow(pOut, (int)nByte, 0) ){
  2642   2649       goto no_mem;
  2643   2650     }
  2644   2651     zNewRecord = (u8 *)pOut->z;
  2645   2652   
  2646   2653     /* Write the record */
  2647   2654     i = putVarint32(zNewRecord, nHdr);
  2648         -  for(pRec=pData0; pRec<=pLast; pRec++){
         2655  +  j = nHdr;
         2656  +  assert( pData0<=pLast );
         2657  +  pRec = pData0;
         2658  +  do{
  2649   2659       serial_type = sqlite3VdbeSerialType(pRec, file_format);
  2650   2660       i += putVarint32(&zNewRecord[i], serial_type);      /* serial type */
  2651         -  }
  2652         -  for(pRec=pData0; pRec<=pLast; pRec++){  /* serial data */
  2653         -    i += sqlite3VdbeSerialPut(&zNewRecord[i], (int)(nByte-i), pRec,file_format);
  2654         -  }
  2655         -  assert( i==nByte );
         2661  +    j += sqlite3VdbeSerialPut(&zNewRecord[j], (int)(nByte-j), pRec,file_format);
         2662  +  }while( (++pRec)<=pLast );
         2663  +  assert( i==nHdr );
         2664  +  assert( j==nByte );
  2656   2665   
  2657   2666     assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
  2658   2667     pOut->n = (int)nByte;
  2659   2668     pOut->flags = MEM_Blob | MEM_Dyn;
  2660   2669     pOut->xDel = 0;
  2661   2670     if( nZero ){
  2662   2671       pOut->u.nZero = nZero;