SQLite

Check-in [ecbef45011]
Login

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

Overview
Comment:Eliminate the OP_VRowid opcode. The regular OP_Rowid now work for both regular and virtual tables. (CVS 6537)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: ecbef45011f1f98d940b2d3492941213d9f04172
User & Date: drh 2009-04-22 17:15:03.000
Context
2009-04-23
13:22
Rework the column-cache mechanism to be more robust (and more correct). The column-alias cache is currently disabled, (CVS 6538) (check-in: dd4d67a674 user: drh tags: trunk)
2009-04-22
17:15
Eliminate the OP_VRowid opcode. The regular OP_Rowid now work for both regular and virtual tables. (CVS 6537) (check-in: ecbef45011 user: drh tags: trunk)
15:32
Change the OP_Rowid opcode so that a deferred OP_Seek is pending, it simply pulls the rowid from the deferred seek target and does not actually move the cursor or do a seek. Other where.c cleanups. (CVS 6536) (check-in: 1c508a9982 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/expr.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.426 2009/04/08 13:51:51 drh Exp $
*/
#include "sqliteInt.h"

/*
** Return the 'affinity' of the expression pExpr if any.
**
** If pExpr is a column, a reference to a column via an 'AS' alias,







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.427 2009/04/22 17:15:03 drh Exp $
*/
#include "sqliteInt.h"

/*
** Return the 'affinity' of the expression pExpr if any.
**
** If pExpr is a column, a reference to a column via an 'AS' alias,
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
      VdbeComment((v, "OPT: tab%d.col%d -> r%d", iTable, iColumn, p->iReg));
#endif
      return p->iReg;
    }
  }  
  assert( v!=0 );
  if( iColumn<0 ){
    int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid;
    sqlite3VdbeAddOp2(v, op, iTable, iReg);
  }else if( pTab==0 ){
    sqlite3VdbeAddOp3(v, OP_Column, iTable, iColumn, iReg);
  }else{
    int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
    sqlite3VdbeAddOp3(v, op, iTable, iColumn, iReg);
    sqlite3ColumnDefault(v, pTab, iColumn);
#ifndef SQLITE_OMIT_FLOATING_POINT







<
|







1741
1742
1743
1744
1745
1746
1747

1748
1749
1750
1751
1752
1753
1754
1755
      VdbeComment((v, "OPT: tab%d.col%d -> r%d", iTable, iColumn, p->iReg));
#endif
      return p->iReg;
    }
  }  
  assert( v!=0 );
  if( iColumn<0 ){

    sqlite3VdbeAddOp2(v, OP_Rowid, iTable, iReg);
  }else if( pTab==0 ){
    sqlite3VdbeAddOp3(v, OP_Column, iTable, iColumn, iReg);
  }else{
    int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
    sqlite3VdbeAddOp3(v, op, iTable, iColumn, iReg);
    sqlite3ColumnDefault(v, pTab, iColumn);
#ifndef SQLITE_OMIT_FLOATING_POINT
Changes to src/update.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.196 2009/02/28 10:47:42 danielk1977 Exp $
*/
#include "sqliteInt.h"

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Forward declaration */
static void updateVirtualTable(
  Parse *pParse,       /* The parsing context */







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.197 2009/04/22 17:15:03 drh Exp $
*/
#include "sqliteInt.h"

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Forward declaration */
static void updateVirtualTable(
  Parse *pParse,       /* The parsing context */
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0,
                             WHERE_ONEPASS_DESIRED, 0);
  if( pWInfo==0 ) goto update_cleanup;
  okOnePass = pWInfo->okOnePass;

  /* Remember the rowid of every item to be updated.
  */
  sqlite3VdbeAddOp2(v, IsVirtual(pTab)?OP_VRowid:OP_Rowid, iCur, regOldRowid);
  if( !okOnePass ){
    regRowSet = ++pParse->nMem;
    sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
  }

  /* End the database scan loop.
  */







|







348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0,
                             WHERE_ONEPASS_DESIRED, 0);
  if( pWInfo==0 ) goto update_cleanup;
  okOnePass = pWInfo->okOnePass;

  /* Remember the rowid of every item to be updated.
  */
  sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regOldRowid);
  if( !okOnePass ){
    regRowSet = ++pParse->nMem;
    sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
  }

  /* End the database scan loop.
  */
Changes to src/vdbe.c.
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
**
** 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.838 2009/04/22 15:32:59 drh Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes.  The test







|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
**
** 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.839 2009/04/22 17:15:03 drh Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes.  The test
3892
3893
3894
3895
3896
3897
3898




3899
3900
3901
3902
3903
3904
3905
3906
3907



3908
3909
















3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
  break;
}

/* Opcode: Rowid P1 P2 * * *
**
** Store in register P2 an integer which is the key of the table entry that
** P1 is currently point to.




*/
case OP_Rowid: {                 /* out2-prerelease */
  int i = pOp->p1;
  VdbeCursor *pC;
  i64 v;

  assert( i>=0 && i<p->nCursor );
  pC = p->apCsr[i];
  assert( pC!=0 );



  if( pC->deferredMoveto ){
    v = pC->movetoTarget;
















  }else{
    rc = sqlite3VdbeCursorMoveto(pC);
    if( rc ) goto abort_due_to_error;
    if( pC->rowidIsValid ){
      v = pC->lastRowid;
    }else if( pC->pseudoTable ){
      v = keyToInt(pC->iKey);
    }else if( pC->nullRow ){
      /* Leave the rowid set to a NULL */
      break;
    }else{
      assert( pC->pCursor!=0 );
      sqlite3BtreeKeySize(pC->pCursor, &v);
      v = keyToInt(v);
    }
  }
  pOut->u.i = v;







>
>
>
>









>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





<
<
<
<
<







3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937





3938
3939
3940
3941
3942
3943
3944
  break;
}

/* Opcode: Rowid P1 P2 * * *
**
** Store in register P2 an integer which is the key of the table entry that
** P1 is currently point to.
**
** P1 can be either an ordinary table or a virtual table.  There used to
** be a separate OP_VRowid opcode for use with virtual tables, but this
** one opcode now works for both table types.
*/
case OP_Rowid: {                 /* out2-prerelease */
  int i = pOp->p1;
  VdbeCursor *pC;
  i64 v;

  assert( i>=0 && i<p->nCursor );
  pC = p->apCsr[i];
  assert( pC!=0 );
  if( pC->nullRow ){
    /* Do nothing so that reg[P2] remains NULL */
    break;
  }else if( pC->deferredMoveto ){
    v = pC->movetoTarget;
  }else if( pC->pseudoTable ){
    v = keyToInt(pC->iKey);
#ifndef SQLITE_OMIT_VIRTUALTABLE
  }else if( pC->pVtabCursor ){
    sqlite3_vtab *pVtab;
    const sqlite3_module *pModule;
    pVtab = pC->pVtabCursor->pVtab;
    pModule = pVtab->pModule;
    assert( pModule->xRowid );
    if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
    rc = pModule->xRowid(pC->pVtabCursor, &v);
    sqlite3DbFree(db, p->zErrMsg);
    p->zErrMsg = pVtab->zErrMsg;
    pVtab->zErrMsg = 0;
    if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
#endif /* SQLITE_OMIT_VIRTUALTABLE */
  }else{
    rc = sqlite3VdbeCursorMoveto(pC);
    if( rc ) goto abort_due_to_error;
    if( pC->rowidIsValid ){
      v = pC->lastRowid;





    }else{
      assert( pC->pCursor!=0 );
      sqlite3BtreeKeySize(pC->pCursor, &v);
      v = keyToInt(v);
    }
  }
  pOut->u.i = v;
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
      pc = pOp->p2 - 1;
    }
  }
  pCur->nullRow = 0;

  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VRowid P1 P2 * * *
**
** Store into register P2  the rowid of
** the virtual-table that the P1 cursor is pointing to.
*/
case OP_VRowid: {             /* out2-prerelease */
  sqlite3_vtab *pVtab;
  const sqlite3_module *pModule;
  sqlite_int64 iRow;
  VdbeCursor *pCur = p->apCsr[pOp->p1];

  assert( pCur->pVtabCursor );
  if( pCur->nullRow ){
    break;
  }
  pVtab = pCur->pVtabCursor->pVtab;
  pModule = pVtab->pModule;
  assert( pModule->xRowid );
  if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
  rc = pModule->xRowid(pCur->pVtabCursor, &iRow);
  sqlite3DbFree(db, p->zErrMsg);
  p->zErrMsg = pVtab->zErrMsg;
  pVtab->zErrMsg = 0;
  if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
  MemSetTypeFlag(pOut, MEM_Int);
  pOut->u.i = iRow;
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VColumn P1 P2 P3 * *
**
** Store the value of the P2-th column of
** the row of the virtual-table that the 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







5105
5106
5107
5108
5109
5110
5111































5112
5113
5114
5115
5116
5117
5118
      pc = pOp->p2 - 1;
    }
  }
  pCur->nullRow = 0;

  break;
}































#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VColumn P1 P2 P3 * *
**
** Store the value of the P2-th column of
** the row of the virtual-table that the 
Changes to src/where.c.
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is responsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** so is applicable.  Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.386 2009/04/22 15:32:59 drh Exp $
*/
#include "sqliteInt.h"

/*
** Trace output macros
*/
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is responsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** so is applicable.  Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.387 2009/04/22 17:15:03 drh Exp $
*/
#include "sqliteInt.h"

/*
** Trace output macros
*/
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
    assert( regRowSet>0 );
    if( iRowidReg==0 ){
      /* The rowid was not available as a side-effect of the code 
      ** genenerated above. So extract it from the cursor now.
      */
      assert( iReleaseReg==0 );
      iReleaseReg = iRowidReg = sqlite3GetTempReg(pParse);
#ifndef SQLITE_OMIT_VIRTUALTABLE
      if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
        sqlite3VdbeAddOp2(v, OP_VRowid, iCur, iRowidReg);
      }else
#endif
      {
        sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
      }
    }
    
    if( pWInfo->wctrlFlags&WHERE_FILL_ROWSET ){
      sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, iRowidReg);
      VVA_ONLY( pWInfo->iRowidHandler = 0; )
    }else{
      assert( pWInfo->wctrlFlags&WHERE_FILL_ROWTEST );







<
<
<
<
<
<
|
<







2971
2972
2973
2974
2975
2976
2977






2978

2979
2980
2981
2982
2983
2984
2985
    assert( regRowSet>0 );
    if( iRowidReg==0 ){
      /* The rowid was not available as a side-effect of the code 
      ** genenerated above. So extract it from the cursor now.
      */
      assert( iReleaseReg==0 );
      iReleaseReg = iRowidReg = sqlite3GetTempReg(pParse);






      sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);

    }
    
    if( pWInfo->wctrlFlags&WHERE_FILL_ROWSET ){
      sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, iRowidReg);
      VVA_ONLY( pWInfo->iRowidHandler = 0; )
    }else{
      assert( pWInfo->wctrlFlags&WHERE_FILL_ROWTEST );