SQLite

Check-in [d0af59fe6b]
Login

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

Overview
Comment:Speed improvement by avoiding a call to sqliteBtreeLast() when inserting a new row into a table. (CVS 763)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d0af59fe6b9d5d026786e7cce1c49c208a0335cc
User & Date: drh 2002-10-19 20:16:38.000
Context
2002-10-20
15:46
Make sure malloc(0) always returns NULL. Fix for ticket #171. (CVS 764) (check-in: 4622b7ce8f user: drh tags: trunk)
2002-10-19
20:16
Speed improvement by avoiding a call to sqliteBtreeLast() when inserting a new row into a table. (CVS 763) (check-in: d0af59fe6b user: drh tags: trunk)
20:13
Fix the URL for pointing to MinGW on the homepage. (CVS 762) (check-in: 16aad98aad user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/vdbe.c.
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
**
** 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.179 2002/09/17 03:20:46 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The makefile scans this source file and creates the following
** array of string constants which are the names of all VDBE opcodes.







|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
**
** 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.180 2002/10/19 20:16:38 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The makefile scans this source file and creates the following
** array of string constants which are the names of all VDBE opcodes.
79
80
81
82
83
84
85

86
87
88
89
90

91
92
93
94
95
96
97
** 
** Every cursor that the virtual machine has open is represented by an
** instance of the following structure.
*/
struct Cursor {
  BtCursor *pCursor;    /* The cursor structure of the backend */
  int lastRecno;        /* Last recno from a Next or NextIdx operation */

  Bool recnoIsValid;    /* True if lastRecno is valid */
  Bool keyAsData;       /* The OP_Column command works on key instead of data */
  Bool atFirst;         /* True if pointing to first entry */
  Bool useRandomRowid;  /* Generate new record numbers semi-randomly */
  Bool nullRow;         /* True if pointing to a row with no data */

  Btree *pBt;           /* Separate file holding temporary table */
};
typedef struct Cursor Cursor;

/*
** A sorter builds a list of elements to be sorted.  Each element of
** the list is an instance of the following structure.







>





>







79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
** 
** Every cursor that the virtual machine has open is represented by an
** instance of the following structure.
*/
struct Cursor {
  BtCursor *pCursor;    /* The cursor structure of the backend */
  int lastRecno;        /* Last recno from a Next or NextIdx operation */
  int nextRowid;        /* Next rowid returned by OP_NewRowid */
  Bool recnoIsValid;    /* True if lastRecno is valid */
  Bool keyAsData;       /* The OP_Column command works on key instead of data */
  Bool atFirst;         /* True if pointing to first entry */
  Bool useRandomRowid;  /* Generate new record numbers semi-randomly */
  Bool nullRow;         /* True if pointing to a row with no data */
  Bool nextRowidValid;  /* True if the nextRowid field is valid */
  Btree *pBt;           /* Separate file holding temporary table */
};
typedef struct Cursor Cursor;

/*
** A sorter builds a list of elements to be sorted.  Each element of
** the list is an instance of the following structure.
3556
3557
3558
3559
3560
3561
3562



3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573







3574
3575
3576
3577
3578
3579
3580
    ** first few attempts at chosing a random rowid pick values just a little
    ** larger than the previous rowid.  This has been shown experimentally
    ** to double the speed of the COPY operation.
    */
    int res, rx, cnt, x;
    cnt = 0;
    if( !pC->useRandomRowid ){



      rx = sqliteBtreeLast(pC->pCursor, &res);
      if( res ){
        v = 1;
      }else{
        sqliteBtreeKey(pC->pCursor, 0, sizeof(v), (void*)&v);
        v = keyToInt(v);
        if( v==0x7fffffff ){
          pC->useRandomRowid = 1;
        }else{
          v++;
        }







      }
    }
    if( pC->useRandomRowid ){
      v = db->priorNewRowid;
      cnt = 0;
      do{
        if( v==0 || cnt>2 ){







>
>
>
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>







3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
    ** first few attempts at chosing a random rowid pick values just a little
    ** larger than the previous rowid.  This has been shown experimentally
    ** to double the speed of the COPY operation.
    */
    int res, rx, cnt, x;
    cnt = 0;
    if( !pC->useRandomRowid ){
      if( pC->nextRowidValid ){
        v = pC->nextRowid;
      }else{
        rx = sqliteBtreeLast(pC->pCursor, &res);
        if( res ){
          v = 1;
        }else{
          sqliteBtreeKey(pC->pCursor, 0, sizeof(v), (void*)&v);
          v = keyToInt(v);
          if( v==0x7fffffff ){
            pC->useRandomRowid = 1;
          }else{
            v++;
          }
        }
      }
      if( v<0x7fffffff ){
        pC->nextRowidValid = 1;
        pC->nextRowid = v+1;
      }else{
        pC->nextRowidValid = 0;
      }
    }
    if( pC->useRandomRowid ){
      v = db->priorNewRowid;
      cnt = 0;
      do{
        if( v==0 || cnt>2 ){
3623
3624
3625
3626
3627
3628
3629

3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644


3645

3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668

3669
3670

3671
3672
3673
3674
3675
3676
3677
** be a string.  The stack is popped twice by this instruction.
*/
case OP_PutIntKey:
case OP_PutStrKey: {
  int tos = p->tos;
  int nos = p->tos-1;
  int i = pOp->p1;

  VERIFY( if( nos<0 ) goto not_enough_stack; )
  if( VERIFY( i>=0 && i<p->nCursor && ) p->aCsr[i].pCursor!=0 ){
    char *zKey;
    int nKey, iKey;
    if( pOp->opcode==OP_PutStrKey ){
      if( Stringify(p, nos) ) goto no_mem;
      nKey = aStack[nos].n;
      zKey = zStack[nos];
    }else{
      assert( aStack[nos].flags & STK_Int );
      nKey = sizeof(int);
      iKey = intToKey(aStack[nos].i);
      zKey = (char*)&iKey;
      db->lastRowid = aStack[nos].i;
      if( pOp->p2 ) db->nChange++;


    }

    rc = sqliteBtreeInsert(p->aCsr[i].pCursor, zKey, nKey,
                        zStack[tos], aStack[tos].n);
    p->aCsr[i].recnoIsValid = 0;
  }
  POPSTACK;
  POPSTACK;
  break;
}

/* Opcode: Delete P1 P2 *
**
** Delete the record at which the P1 cursor is currently pointing.
**
** The cursor will be left pointing at either the next or the previous
** record in the table. If it is left pointing at the next record, then
** the next Next instruction will be a no-op.  Hence it is OK to delete
** a record from within an Next loop.
**
** The row change counter is incremented if P2==1 and is unmodified
** if P2==0.
*/
case OP_Delete: {
  int i = pOp->p1;

  if( VERIFY( i>=0 && i<p->nCursor && ) p->aCsr[i].pCursor!=0 ){
    rc = sqliteBtreeDelete(p->aCsr[i].pCursor);

  }
  if( pOp->p2 ) db->nChange++;
  break;
}

/* Opcode: KeyAsData P1 P2 *
**







>

|













>
>
|
>
|

|




















>
|
|
>







3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
** be a string.  The stack is popped twice by this instruction.
*/
case OP_PutIntKey:
case OP_PutStrKey: {
  int tos = p->tos;
  int nos = p->tos-1;
  int i = pOp->p1;
  Cursor *pC;
  VERIFY( if( nos<0 ) goto not_enough_stack; )
  if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){
    char *zKey;
    int nKey, iKey;
    if( pOp->opcode==OP_PutStrKey ){
      if( Stringify(p, nos) ) goto no_mem;
      nKey = aStack[nos].n;
      zKey = zStack[nos];
    }else{
      assert( aStack[nos].flags & STK_Int );
      nKey = sizeof(int);
      iKey = intToKey(aStack[nos].i);
      zKey = (char*)&iKey;
      db->lastRowid = aStack[nos].i;
      if( pOp->p2 ) db->nChange++;
      if( pC->nextRowidValid && aStack[nos].i>=pC->nextRowid ){
        pC->nextRowidValid = 0;
      }
    }
    rc = sqliteBtreeInsert(pC->pCursor, zKey, nKey,
                        zStack[tos], aStack[tos].n);
    pC->recnoIsValid = 0;
  }
  POPSTACK;
  POPSTACK;
  break;
}

/* Opcode: Delete P1 P2 *
**
** Delete the record at which the P1 cursor is currently pointing.
**
** The cursor will be left pointing at either the next or the previous
** record in the table. If it is left pointing at the next record, then
** the next Next instruction will be a no-op.  Hence it is OK to delete
** a record from within an Next loop.
**
** The row change counter is incremented if P2==1 and is unmodified
** if P2==0.
*/
case OP_Delete: {
  int i = pOp->p1;
  Cursor *pC;
  if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){
    rc = sqliteBtreeDelete(pC->pCursor);
    pC->nextRowidValid = 0;
  }
  if( pOp->p2 ) db->nChange++;
  break;
}

/* Opcode: KeyAsData P1 P2 *
**