Add the OPFLAG_MULTICOLUMN flat to the OP_Column opcode.  Rearrange OP_Column
instrunctions to take advantage of the new flag for a small performance 
increase

FossilOrigin-Name: 5e5d6e8680b253b4de5c04df155c27f15fedc0c1
diff --git a/manifest b/manifest
index c39ace7..1c59731 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sthe\sheader\scomment\sin\ssqlite3VdbeDeletePriorOpcode().\s\sNo\schanges\sto\ncode.
-D 2014-09-29T15:42:01.115
+C Add\sthe\sOPFLAG_MULTICOLUMN\sflat\sto\sthe\sOP_Column\sopcode.\s\sRearrange\sOP_Column\ninstrunctions\sto\stake\sadvantage\sof\sthe\snew\sflag\sfor\sa\ssmall\sperformance\s\nincrease
+D 2014-09-29T18:47:20.017
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -181,7 +181,7 @@
 F src/ctime.c bb434068b5308a857b181c2d204a320ff0d6c638
 F src/date.c 57a7f9ba9f6b4d5268f5e411739066a611f99036
 F src/delete.c fae81cc2eb14b75267d4f47d3cfc9ae02aae726f
-F src/expr.c f32119248996680aa73c5c37bfdd42820804dc17
+F src/expr.c 622ca88bb258292690a550ca0c290ec7b071bed4
 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
 F src/fkey.c da985ae673efef2c712caef825a5d2edb087ead7
 F src/func.c ba47c1671ab3cfdafa6e9d6ee490939ea578adee
@@ -227,12 +227,12 @@
 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
 F src/resolve.c a3466128b52a86c466e47ac1a19e2174f7b5cf89
 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
-F src/select.c a83ed8bc2a31c131e3addb6f0488b68334085e7b
+F src/select.c 6e7d7a277307ebee1a284d8811a8a3351ffc39b2
 F src/shell.c dad23987c34faddb061a339da3e92e05ccc6935e
 F src/sqlite.h.in 8b018219ce988913e5977d5de9ab4beb33be23b6
 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
 F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
-F src/sqliteInt.h 5e09fe04f999223680801ddf8fbae6b60751d613
+F src/sqliteInt.h ba443d9af2cef399e2ec641d44d005212b1476ef
 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
 F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
 F src/table.c 2e99ef7ef16187e17033d9398dc962ce22dab5cb
@@ -285,15 +285,15 @@
 F src/threads.c 22dded4283dc4b25422f6444cdcb8d6b1ea0b5ff
 F src/tokenize.c cc9016e5007fc5e76789079616d2f26741bcc689
 F src/trigger.c 25571661fdeae8c7f975ff40ffec205520a3f92f
-F src/update.c 729f6f18fc27740591d085e1172cebe311144bf0
+F src/update.c dcc1733c8f9d455a3127e2b151a211fa7f9ef053
 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
 F src/util.c 4006c01772bd8d8ac4306d523bbcee41d3e392d8
 F src/vacuum.c 59f03f92bcff57faa6a8ca256eb29ccddfb0614a
-F src/vdbe.c 93eeb6f9c3a3084133225a196f220454d71cca10
-F src/vdbe.h 09f5b4e3719fa454f252322b1cdab5cf1f361327
+F src/vdbe.c 89636b004debc955452f6e0f26dfcc13cc96676b
+F src/vdbe.h d5825ae515ab108331739bd4910eb66dd0eb33f0
 F src/vdbeInt.h bb7f7ecfdead1a2ae0251b59f86f5724838d975c
 F src/vdbeapi.c e9e33b59834e3edc8790209765e069874c269d9d
-F src/vdbeaux.c 8e016c6051c013a394f8e8679be1ca60723707bd
+F src/vdbeaux.c f8df1050cb0e5f7d537bda4dc6caa44d44ab87bc
 F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4
 F src/vdbemem.c 1e105dacf5190fc85a8ec2107c0dcc1884e75099
 F src/vdbesort.c 5c1bacf90578d22b630fbf6ed98ccf60d83435ef
@@ -1200,7 +1200,10 @@
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 414f0d6a647a4d040b5463c73c5e15e699d85b4c
-R f6298f1a1c0cd9e9dc9c3dc07f24407e
+P 7fb1626866c2f8dad84c7e6184824be3efd71ca2
+R 58d61b9e8ed6b972c827aa4b2de6a9d8
+T *branch * faster-OP_Column
+T *sym-faster-OP_Column *
+T -sym-trunk *
 U drh
-Z 0f82639c06e932d5523a9215bf58cd9c
+Z bc7d4115a8f75585e68aa7b7bc067fe4
diff --git a/manifest.uuid b/manifest.uuid
index b5ea57e..59185e9 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-7fb1626866c2f8dad84c7e6184824be3efd71ca2
\ No newline at end of file
+5e5d6e8680b253b4de5c04df155c27f15fedc0c1
\ No newline at end of file
diff --git a/src/expr.c b/src/expr.c
index 57e462e..64dcbae 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -2381,6 +2381,7 @@
   }
   if( iCol>=0 ){
     sqlite3ColumnDefault(v, pTab, iCol, regOut);
+    sqlite3VdbeOptimizeColumnOpcodes(v);
   }
 }
 
diff --git a/src/select.c b/src/select.c
index 7820833..5e0c03b 100644
--- a/src/select.c
+++ b/src/select.c
@@ -706,7 +706,7 @@
   pDest->nSdst = nResultCol;
   regResult = pDest->iSdst;
   if( srcTab>=0 ){
-    for(i=0; i<nResultCol; i++){
+    for(i=nResultCol-1; i>=0; i--){
       sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);
       VdbeComment((v, "%s", pEList->a[i].zName));
     }
@@ -1225,10 +1225,11 @@
     p5 = 0;
     bSeq = 1;
   }
-  for(i=0; i<nSortData; i++){
+  for(i=nSortData-1; i>=0; i--){
     sqlite3VdbeAddOp3(v, OP_Column, iSortTab, nKey+bSeq+i, regRow+i);
-    if( i==0 ) sqlite3VdbeChangeP5(v, p5);
+    sqlite3VdbeChangeP5(v, p5);
     VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan));
+    p5 = 0;
   }
   switch( eDest ){
     case SRT_Table:
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index b7e4d07..7ec6336 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -2665,6 +2665,7 @@
 #define OPFLAG_BULKCSR       0x01    /* OP_Open** used to open bulk cursor */
 #define OPFLAG_P2ISREG       0x02    /* P2 to OP_Open** is a register number */
 #define OPFLAG_PERMUTE       0x01    /* OP_Compare: use the permutation */
+#define OPFLAG_MULTICOLUMN   0x10    /* OP_Column followed by another */
 
 /*
  * Each trigger present in the database schema is stored as an instance of
diff --git a/src/update.c b/src/update.c
index f781a60..8a7774c 100644
--- a/src/update.c
+++ b/src/update.c
@@ -73,6 +73,7 @@
     }
 #ifndef SQLITE_OMIT_FLOATING_POINT
     if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
+      sqlite3VdbeOptimizeColumnOpcodes(v);
       sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
     }
 #endif
diff --git a/src/vdbe.c b/src/vdbe.c
index 34eb1d4..5e2ca39 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -2266,9 +2266,11 @@
   u32 avail;         /* Number of bytes of available data */
   u32 t;             /* A type code from the record header */
   u16 fx;            /* pDest->flags value */
+  u8 p5;
   Mem *pReg;         /* PseudoTable input register */
 
   p2 = pOp->p2;
+  p5 = 0;
   assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
   pDest = &aMem[pOp->p3];
   memAboutToChange(p, pDest);
@@ -2436,22 +2438,32 @@
     }
   }
 
-  /* Extract the content for the p2+1-th column.  Control can only
-  ** reach this point if aOffset[p2], aOffset[p2+1], and pC->aType[p2] are
-  ** all valid.
+  /* At this point, all of the following values are set:
+  **
+  **    p2             Index of column to extract.  pOp->p2.
+  **    pDest          Memory register into which to write result
+  **    pC->aRow       Binary row content from the btree.  Might be incomplete
+  **    pC->szRow      Number of bytes in pC->szRow
+  **    aOffset[p2]    Offset into the binary row where P2-th column starts
+  **    aOffste[p2+1]  Offset into binary row of first byte past P2-th column
+  **    pC->aType[p2]  Datatype of the P2-th column (as stored on disk)
+  **
+  ** Extract the content for column number p2.
   */
+op_column_decode:
   assert( p2<pC->nHdrParsed );
   assert( rc==SQLITE_OK );
   assert( sqlite3VdbeCheckMemInvariants(pDest) );
   if( VdbeMemDynamic(pDest) ) sqlite3VdbeMemSetNull(pDest);
   t = pC->aType[p2];
+  p5 = pOp->p5;
   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], t, pDest);
   }else{
     /* This branch happens only when content is on overflow pages */
-    if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
+    if( ((p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
           && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0))
      || (len = sqlite3VdbeSerialTypeLen(t))==0
     ){
@@ -2495,6 +2507,23 @@
 op_column_error:
   UPDATE_MAX_BLOBSIZE(pDest);
   REGISTER_TRACE(pOp->p3, pDest);
+
+  /* If the OPFLAG_MULTICOLUMN bit is set on P5, that means that this
+  ** OP_Column is immediately followed by another OP_Column with the same
+  ** P1 and a P2 that is no larger than the current P2.  In that case, 
+  ** process the following OP_Column as part of this instruction, without
+  ** returning to the main instruction dispatch loop.
+  */
+  if( (p5 & OPFLAG_MULTICOLUMN)!=0 && rc==0 ){
+    pc++;
+    assert( pOp[1].opcode==OP_Column );
+    assert( pOp[1].p1==pOp[0].p1 );
+    assert( pOp[1].p2<=pOp[0].p2 );
+    pOp++;
+    p2 = pOp->p2;
+    pDest = &aMem[pOp->p3];
+    goto op_column_decode;
+  }
   break;
 }
 
diff --git a/src/vdbe.h b/src/vdbe.h
index f975f95..b977d3c 100644
--- a/src/vdbe.h
+++ b/src/vdbe.h
@@ -179,6 +179,7 @@
 void sqlite3VdbeJumpHere(Vdbe*, int addr);
 void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
 int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
+void sqlite3VdbeOptimizeColumnOpcodes(Vdbe*);
 void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
 void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
 void sqlite3VdbeUsesBtree(Vdbe*, int);
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index 2562c63..3f3f8d0 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -502,6 +502,15 @@
         pOp->p4type = P4_ADVANCE;
         break;
       }
+      case OP_Column: {
+        if( pOp[1].opcode==OP_Column
+         && pOp[1].p1==pOp->p1
+         && pOp[1].p2<=pOp->p2 
+        ){
+          pOp->p5 |= OPFLAG_MULTICOLUMN;
+        }
+        break;
+      }
     }
 
     pOp->opflags = sqlite3OpcodeProperty[opcode];
@@ -765,6 +774,30 @@
 }
 
 /*
+** When running multiple OP_Column opcodes in a row, it is advantagous
+** to run the one with the largest P2 value (the largest column number)
+** first.  This routine checks the last few OP_Column opcodes and 
+** might reorder them so that a larger P2 value opertion occurs at
+** the start of the list.
+*/
+void sqlite3VdbeOptimizeColumnOpcodes(Vdbe *p){
+  VdbeOp *aOp, tempOp;
+  int i;
+  aOp = p->aOp;
+  i = p->nOp-2;
+  while( i>p->pParse->iFixedOp
+      && aOp[i+1].opcode==OP_Column
+      && aOp[i].opcode==OP_Column
+      && aOp[i].p1==aOp[i+1].p1
+      && aOp[i].p2<aOp[i+1].p2 ){
+    tempOp = aOp[i];
+    aOp[i] = aOp[i+1];
+    aOp[i+1] = tempOp;
+    i--;
+  }
+}
+
+/*
 ** Change the value of the P4 operand for a specific instruction.
 ** This routine is useful when a large program is loaded from a
 ** static array using sqlite3VdbeAddOpList but we want to make a