SQLite

Changes On Branch function-ctx-cache
Login

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

Changes In Branch function-ctx-cache Excluding Merge-Ins

This is equivalent to a diff from 015302f1 to 2f31bdd1

2015-06-26
13:31
Cache the most recently sqlite3_context used by OP_Function and reuse it on subsequent calls, if appropriate. This gives a noticable performance boost. (Closed-Leaf check-in: 2f31bdd1 user: drh tags: function-ctx-cache)
03:12
Fix harmless compiler warning in assert statement. (check-in: 7097716c user: mistachkin tags: trunk)
02:41
Simplify the pcache by not keeping continuous track of page 1 but instead just loading page 1 on the rare occasions when it is actually needed. (check-in: 015302f1 user: drh tags: trunk)
2015-06-25
23:52
Optimization to sqlite3_value_bytes() for the common case that does not require a data transformation. (check-in: 8d79f3a1 user: drh tags: trunk)

Changes to src/vdbe.c.

558
559
560
561
562
563
564



565
566
567
568
569
570
571
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574







+
+
+







  Mem *pIn3 = 0;             /* 3rd input operand */
  Mem *pOut = 0;             /* Output operand */
  int *aPermute = 0;         /* Permutation of columns for OP_Compare */
  i64 lastRowid = db->lastRowid;  /* Saved value of the last insert ROWID */
#ifdef VDBE_PROFILE
  u64 start;                 /* CPU clock count at start of opcode */
#endif
  Op *pCtxOp = 0;            /* Opcode for which ctx is initialized */
  sqlite3_context ctx;       /* Function call context */

  /*** INSERT STACK UNION HERE ***/

  assert( p->magic==VDBE_MAGIC_RUN );  /* sqlite3_step() verifies this */
  sqlite3VdbeEnter(p);
  if( p->rc==SQLITE_NOMEM ){
    /* This happens if a malloc() inside a call to sqlite3_column_text() or
    ** sqlite3_column_text16() failed.  */
939
940
941
942
943
944
945

946
947
948
949
950
951
952
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956







+







      ** an IGNORE exception. In this case jump to the address specified
      ** as the p2 of the calling OP_Program.  */
      pcx = p->aOp[pcx].p2-1;
    }
    aOp = p->aOp;
    aMem = p->aMem;
    pOp = &aOp[pcx];
    pCtxOp = 0;
    break;
  }
  p->rc = pOp->p1;
  p->errorAction = (u8)pOp->p2;
  p->pc = pcx;
  if( p->rc ){
    if( pOp->p5 ){
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573

1574
1575
1576
1577




1578
1579
1580
1581
1582
1583




1584
1585

1586
1587
1588

1589
1590
1591
1592
1593













1594
1595
1596
1597

1598
1599
1600
1601
1602
1603
1604
1566
1567
1568
1569
1570
1571
1572

1573
1574
1575
1576
1577




1578
1579
1580
1581

1582




1583
1584
1585
1586


1587



1588





1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604

1605
1606
1607
1608
1609
1610
1611
1612







-




+
-
-
-
-
+
+
+
+
-

-
-
-
-
+
+
+
+
-
-
+
-
-
-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+







** invocation of this opcode.
**
** See also: AggStep and AggFinal
*/
case OP_Function: {
  int i;
  Mem *pArg;
  sqlite3_context ctx;
  sqlite3_value **apVal;
  int n;

  n = pOp->p5;
  if( pOp!=pCtxOp ){
  apVal = p->apArg;
  assert( apVal || n==0 );
  assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
  ctx.pOut = &aMem[pOp->p3];
    apVal = p->apArg;
    assert( apVal || n==0 );
    assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
    ctx.pOut = &aMem[pOp->p3];
  memAboutToChange(p, ctx.pOut);

  assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) );
  assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
  pArg = &aMem[pOp->p2];
  for(i=0; i<n; i++, pArg++){
    assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) );
    assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
    pArg = &aMem[pOp->p2];
    for(i=0; i<n; i++, pArg++){
    assert( memIsValid(pArg) );
    apVal[i] = pArg;
      apVal[i] = pArg;
    Deephemeralize(pArg);
    REGISTER_TRACE(pOp->p2+i, pArg);
  }
    }

  assert( pOp->p4type==P4_FUNCDEF );
  ctx.pFunc = pOp->p4.pFunc;
  ctx.iOp = (int)(pOp - aOp);
  ctx.pVdbe = p;
    assert( pOp->p4type==P4_FUNCDEF );
    ctx.pFunc = pOp->p4.pFunc;
    ctx.iOp = (int)(pOp - aOp);
    ctx.pVdbe = p;
    pCtxOp = pOp;
  }
#ifdef SQLITE_DEBUG
  for(i=0; i<n; i++){
    assert( memIsValid(p->apArg[i]) );
    REGISTER_TRACE(pOp->p2+i, p->apArg[i]);
  }
#endif
  memAboutToChange(p, ctx.pOut);
  MemSetTypeFlag(ctx.pOut, MEM_Null);
  ctx.fErrorOrAux = 0;
  db->lastRowid = lastRowid;
  (*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */
  (*ctx.pFunc->xFunc)(&ctx, n, p->apArg); /* IMP: R-24505-23230 */
  lastRowid = db->lastRowid;  /* Remember rowid changes made by xFunc */

  /* If the function returned an error, throw an exception */
  if( ctx.fErrorOrAux ){
    if( ctx.isError ){
      sqlite3VdbeError(p, "%s", sqlite3_value_text(ctx.pOut));
      rc = ctx.isError;
5500
5501
5502
5503
5504
5505
5506

5507
5508
5509
5510
5511
5512
5513
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522







+







  p->nChange = 0;
  p->pFrame = pFrame;
  p->aMem = aMem = &VdbeFrameMem(pFrame)[-1];
  p->nMem = pFrame->nChildMem;
  p->nCursor = (u16)pFrame->nChildCsr;
  p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
  p->aOp = aOp = pProgram->aOp;
  pCtxOp = 0;
  p->nOp = pProgram->nOp;
  p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor];
  p->nOnceFlag = pProgram->nOnce;
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  p->anExec = 0;
#endif
  pOp = &aOp[-1];
5710
5711
5712
5713
5714
5715
5716
5717

5718
5719
5720
5721
5722

5723
5724
5725
5726
5727
5728
5729
5730

5731
5732

5733
5734
5735
5736
5737
5738
5739
5740
5741







5742
5743

5744
5745

5746
5747
5748
5749
5750
5751
5752
5719
5720
5721
5722
5723
5724
5725

5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739

5740
5741

5742
5743
5744







5745
5746
5747
5748
5749
5750
5751
5752

5753
5754

5755
5756
5757
5758
5759
5760
5761
5762







-
+





+







-
+

-
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
+

-
+







*/
case OP_AggStep: {
  int n;
  int i;
  Mem *pMem;
  Mem *pRec;
  Mem t;
  sqlite3_context ctx;
  sqlite3_context actx;
  sqlite3_value **apVal;

  n = pOp->p5;
  assert( n>=0 );
  pRec = &aMem[pOp->p2];
  pCtxOp = 0;
  apVal = p->apArg;
  assert( apVal || n==0 );
  for(i=0; i<n; i++, pRec++){
    assert( memIsValid(pRec) );
    apVal[i] = pRec;
    memAboutToChange(p, pRec);
  }
  ctx.pFunc = pOp->p4.pFunc;
  actx.pFunc = pOp->p4.pFunc;
  assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
  ctx.pMem = pMem = &aMem[pOp->p3];
  actx.pMem = pMem = &aMem[pOp->p3];
  pMem->n++;
  sqlite3VdbeMemInit(&t, db, MEM_Null);
  ctx.pOut = &t;
  ctx.isError = 0;
  ctx.pVdbe = p;
  ctx.iOp = (int)(pOp - aOp);
  ctx.skipFlag = 0;
  (ctx.pFunc->xStep)(&ctx, n, apVal); /* IMP: R-24505-23230 */
  if( ctx.isError ){
  actx.pOut = &t;
  actx.isError = 0;
  actx.pVdbe = p;
  actx.iOp = (int)(pOp - aOp);
  actx.skipFlag = 0;
  (actx.pFunc->xStep)(&actx, n, apVal); /* IMP: R-24505-23230 */
  if( actx.isError ){
    sqlite3VdbeError(p, "%s", sqlite3_value_text(&t));
    rc = ctx.isError;
    rc = actx.isError;
  }
  if( ctx.skipFlag ){
  if( actx.skipFlag ){
    assert( pOp[-1].opcode==OP_CollSeq );
    i = pOp[-1].p1;
    if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1);
  }
  sqlite3VdbeMemRelease(&t);
  break;
}
6168
6169
6170
6171
6172
6173
6174

6175
6176
6177
6178
6179
6180
6181
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192







+








  /* Invoke the xFilter method */
  res = 0;
  apArg = p->apArg;
  for(i = 0; i<nArg; i++){
    apArg[i] = &pArgc[i+1];
  }
  pCtxOp = 0;
  rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
  sqlite3VtabImportErrmsg(p, pVtab);
  if( rc==SQLITE_OK ){
    res = pModule->xEof(pVtabCursor);
  }
  pCur->nullRow = 0;
  VdbeBranchTaken(res!=0,2);
6351
6352
6353
6354
6355
6356
6357

6358
6359
6360
6361
6362
6363
6364
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376







+







  }
  pModule = pVtab->pModule;
  nArg = pOp->p2;
  assert( pOp->p4type==P4_VTAB );
  if( ALWAYS(pModule->xUpdate) ){
    u8 vtabOnConflict = db->vtabOnConflict;
    apArg = p->apArg;
    pCtxOp = 0;
    pX = &aMem[pOp->p3];
    for(i=0; i<nArg; i++){
      assert( memIsValid(pX) );
      memAboutToChange(p, pX);
      apArg[i] = pX;
      pX++;
    }