/ Check-in [2c913908]
Login

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

Overview
Comment:Modify FifoRead and FifoWrite to work exclusively with memory cells. (CVS 4676)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 2c913908a47e7ace7d964067e3566d232ee2d494
User & Date: danielk1977 2008-01-04 13:57:26
Context
2008-01-04
16:50
Replace the NOPUSH_MASKs with a bit-vector mechanism that can contain several different properties about each opcode. (CVS 4677) check-in: 042dcb96 user: drh tags: trunk
13:57
Modify FifoRead and FifoWrite to work exclusively with memory cells. (CVS 4676) check-in: 2c913908 user: danielk1977 tags: trunk
13:24
Modify the code generated for a DELETE to use registers instead of the vdbe stack. (CVS 4675) check-in: 173f2813 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/delete.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
228
229
230
231
232
233
234

235
236

237
238
239
240
241

242
243
244
245
246

247
248
249
250
251
252
253
...
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
**    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
** in order to generate code for DELETE FROM statements.
**
** $Id: delete.c,v 1.145 2008/01/04 13:24:29 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.
................................................................................
  if( v==0 ){
    goto delete_from_cleanup;
  }
  if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
  sqlite3BeginWriteOperation(pParse, triggers_exist, iDb);

  if( triggers_exist ){

    int iGoto = sqlite3VdbeAddOp0(v, OP_Goto);
    addr = sqlite3VdbeMakeLabel(v);

    iBeginBeforeTrigger = sqlite3VdbeCurrentAddr(v);
    (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_BEFORE, pTab,
        -1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
        addr, &old_col_mask, 0);
    iEndBeforeTrigger = sqlite3VdbeAddOp0(v, OP_Goto);

    iBeginAfterTrigger = sqlite3VdbeCurrentAddr(v);
    (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1,
        oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
        addr, &old_col_mask, 0);
    iEndAfterTrigger = sqlite3VdbeAddOp0(v, OP_Goto);

    sqlite3VdbeJumpHere(v, iGoto);
  }

  /* If we are trying to delete from a view, realize that view into
  ** a ephemeral table.
  */
  if( isView ){
................................................................................
      }
    }
  } 
  /* The usual case: There is a WHERE clause so we have to scan through
  ** the table and pick which records to delete.
  */
  else{
    int iRowid = ++pParse->nMem;    /* Used for storing value read from fifo */

    /* Begin the database scan
    */
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
    if( pWInfo==0 ) goto delete_from_cleanup;

    /* Remember the rowid of every item to be deleted.
    */
    sqlite3VdbeAddOp1(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur);
    sqlite3VdbeAddOp0(v, OP_FifoWrite);
    if( db->flags & SQLITE_CountRows ){
      sqlite3VdbeAddOp2(v, OP_MemIncr, 1, memCnt);
    }

    /* End the database scan loop.
    */
    sqlite3WhereEnd(pWInfo);







|







 







>


>


<
|

>


<
|

>







 







|








|
|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
228
229
230
231
232
233
234
235
236
237
238
239
240

241
242
243
244
245

246
247
248
249
250
251
252
253
254
255
...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
**    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
** in order to generate code for DELETE FROM statements.
**
** $Id: delete.c,v 1.146 2008/01/04 13:57:26 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.
................................................................................
  if( v==0 ){
    goto delete_from_cleanup;
  }
  if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
  sqlite3BeginWriteOperation(pParse, triggers_exist, iDb);

  if( triggers_exist ){
    int orconf = ((pParse->trigStack)?pParse->trigStack->orconf:OE_Default);
    int iGoto = sqlite3VdbeAddOp0(v, OP_Goto);
    addr = sqlite3VdbeMakeLabel(v);

    iBeginBeforeTrigger = sqlite3VdbeCurrentAddr(v);
    (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_BEFORE, pTab,

        -1, oldIdx, orconf, addr, &old_col_mask, 0);
    iEndBeforeTrigger = sqlite3VdbeAddOp0(v, OP_Goto);

    iBeginAfterTrigger = sqlite3VdbeCurrentAddr(v);
    (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1,

        oldIdx, orconf, addr, &old_col_mask, 0);
    iEndAfterTrigger = sqlite3VdbeAddOp0(v, OP_Goto);

    sqlite3VdbeJumpHere(v, iGoto);
  }

  /* If we are trying to delete from a view, realize that view into
  ** a ephemeral table.
  */
  if( isView ){
................................................................................
      }
    }
  } 
  /* The usual case: There is a WHERE clause so we have to scan through
  ** the table and pick which records to delete.
  */
  else{
    int iRowid = ++pParse->nMem;    /* Used for storing rowid values. */

    /* Begin the database scan
    */
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
    if( pWInfo==0 ) goto delete_from_cleanup;

    /* Remember the rowid of every item to be deleted.
    */
    sqlite3VdbeAddOp2(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur, iRowid);
    sqlite3VdbeAddOp1(v, OP_FifoWrite, iRowid);
    if( db->flags & SQLITE_CountRows ){
      sqlite3VdbeAddOp2(v, OP_MemIncr, 1, memCnt);
    }

    /* End the database scan loop.
    */
    sqlite3WhereEnd(pWInfo);

Changes to src/update.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
102
103
104
105
106
107
108

109
110
111
112
113
114
115
...
339
340
341
342
343
344
345

346
347
348
349
350
351
352
353
354
...
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
...
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
**    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.155 2008/01/03 23:44:53 drh Exp $
*/
#include "sqliteInt.h"

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Forward declaration */
static void updateVirtualTable(
  Parse *pParse,       /* The parsing context */
................................................................................
  Expr *pRowidExpr = 0;  /* Expression defining the new record number */
  int openAll = 0;       /* True if all indices need to be opened */
  AuthContext sContext;  /* The authorization context */
  NameContext sNC;       /* The name-context to resolve expressions in */
  int iDb;               /* Database containing the table being updated */
  int memCnt = 0;        /* Memory cell used for counting rows changed */
  int mem1;      /* Memory address storing the rowid for next row to update */


#ifndef SQLITE_OMIT_TRIGGER
  int isView;                  /* Trying to update a view */
  int triggers_exist = 0;      /* True if any row triggers exist */
#endif
  int iBeginAfterTrigger;      /* Address of after trigger program */
  int iEndAfterTrigger;        /* Exit of after trigger program */
................................................................................
  /* Begin the database scan
  */
  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
  if( pWInfo==0 ) goto update_cleanup;

  /* Remember the rowid of every item to be updated.
  */

  sqlite3VdbeAddOp2(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur, 0);
  sqlite3VdbeAddOp2(v, OP_FifoWrite, 0, 0);

  /* End the database scan loop.
  */
  sqlite3WhereEnd(pWInfo);

  /* Initialize the count of updated rows
  */
................................................................................
      if( openAll || aIdxUsed[i] ){
        KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
        sqlite3VdbeAddOp4(v, OP_OpenWrite, iCur+i+1, pIdx->tnum, iDb,
                       (char*)pKey, P4_KEYINFO_HANDOFF);
        assert( pParse->nTab>iCur+i+1 );
      }
    }

  }
  
  /* Jump back to this point if a trigger encounters an IGNORE constraint. */
  if( triggers_exist ){
    sqlite3VdbeResolveLabel(v, addr);
  }

  /* Top of the update loop */
  addr = sqlite3VdbeAddOp2(v, OP_FifoRead, 0, 0);
  sqlite3VdbeAddOp2(v, OP_StackDepth, -1, 0);
  sqlite3VdbeAddOp2(v, OP_MemStore, mem1, 0);

  if( triggers_exist ){
    /* Make cursor iCur point to the record that is being updated.
    */
    sqlite3VdbeAddOp2(v, OP_NotExists, iCur, addr);

    /* Generate the OLD table
    */
    sqlite3VdbeAddOp2(v, OP_Rowid, iCur, 0);
    if( !old_col_mask ){
      sqlite3VdbeAddOp2(v, OP_Null, 0, 0);
    }else{
................................................................................
      sqlite3TableAffinityStr(v, pTab);
    }
    if( pParse->nErr ) goto update_cleanup;
    sqlite3CodeInsert(pParse, newIdx, 0);

    sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginBeforeTrigger);
    sqlite3VdbeJumpHere(v, iEndBeforeTrigger);

    if( !isView ){
      sqlite3VdbeAddOp2(v, OP_MemLoad, mem1, 0);
    }
  }

  if( !isView && !IsVirtual(pTab) ){

    /* Loop over every record that needs updating.  We have to load
    ** the old data for each record to be updated because some columns
    ** might not change and we will need to copy the old value.
    ** Also, the old data is needed to delete the old index entries.
    ** So make the cursor point at the old record.
    */
    sqlite3VdbeAddOp2(v, OP_NotExists, iCur, addr);
    sqlite3VdbeAddOp2(v, OP_MemLoad, mem1, 0);

    /* If the record number will change, push the record number as it
    ** will be after the update. (The old record number is currently
    ** on top of the stack.)
    */
    if( chngRowid ){
      sqlite3ExprCode(pParse, pRowidExpr, 0);







|







 







>







 







>
|
|







 







<








|

<




|







 







<
<
<
<










|
|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
...
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
...
382
383
384
385
386
387
388

389
390
391
392
393
394
395
396
397
398

399
400
401
402
403
404
405
406
407
408
409
410
...
441
442
443
444
445
446
447




448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
**    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.156 2008/01/04 13:57:26 danielk1977 Exp $
*/
#include "sqliteInt.h"

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Forward declaration */
static void updateVirtualTable(
  Parse *pParse,       /* The parsing context */
................................................................................
  Expr *pRowidExpr = 0;  /* Expression defining the new record number */
  int openAll = 0;       /* True if all indices need to be opened */
  AuthContext sContext;  /* The authorization context */
  NameContext sNC;       /* The name-context to resolve expressions in */
  int iDb;               /* Database containing the table being updated */
  int memCnt = 0;        /* Memory cell used for counting rows changed */
  int mem1;      /* Memory address storing the rowid for next row to update */
  int iRowid;            /* Memory address storing rowids */

#ifndef SQLITE_OMIT_TRIGGER
  int isView;                  /* Trying to update a view */
  int triggers_exist = 0;      /* True if any row triggers exist */
#endif
  int iBeginAfterTrigger;      /* Address of after trigger program */
  int iEndAfterTrigger;        /* Exit of after trigger program */
................................................................................
  /* Begin the database scan
  */
  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
  if( pWInfo==0 ) goto update_cleanup;

  /* Remember the rowid of every item to be updated.
  */
  iRowid = ++pParse->nMem;
  sqlite3VdbeAddOp2(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur, iRowid);
  sqlite3VdbeAddOp2(v, OP_FifoWrite, iRowid, 0);

  /* End the database scan loop.
  */
  sqlite3WhereEnd(pWInfo);

  /* Initialize the count of updated rows
  */
................................................................................
      if( openAll || aIdxUsed[i] ){
        KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
        sqlite3VdbeAddOp4(v, OP_OpenWrite, iCur+i+1, pIdx->tnum, iDb,
                       (char*)pKey, P4_KEYINFO_HANDOFF);
        assert( pParse->nTab>iCur+i+1 );
      }
    }

  }
  
  /* Jump back to this point if a trigger encounters an IGNORE constraint. */
  if( triggers_exist ){
    sqlite3VdbeResolveLabel(v, addr);
  }

  /* Top of the update loop */
  addr = sqlite3VdbeAddOp2(v, OP_FifoRead, iRowid, 0);
  sqlite3VdbeAddOp2(v, OP_StackDepth, -1, 0);


  if( triggers_exist ){
    /* Make cursor iCur point to the record that is being updated.
    */
    sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid);

    /* Generate the OLD table
    */
    sqlite3VdbeAddOp2(v, OP_Rowid, iCur, 0);
    if( !old_col_mask ){
      sqlite3VdbeAddOp2(v, OP_Null, 0, 0);
    }else{
................................................................................
      sqlite3TableAffinityStr(v, pTab);
    }
    if( pParse->nErr ) goto update_cleanup;
    sqlite3CodeInsert(pParse, newIdx, 0);

    sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginBeforeTrigger);
    sqlite3VdbeJumpHere(v, iEndBeforeTrigger);




  }

  if( !isView && !IsVirtual(pTab) ){

    /* Loop over every record that needs updating.  We have to load
    ** the old data for each record to be updated because some columns
    ** might not change and we will need to copy the old value.
    ** Also, the old data is needed to delete the old index entries.
    ** So make the cursor point at the old record.
    */
    sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid);
    sqlite3VdbeAddOp2(v, OP_MemLoad, iRowid, 0);

    /* If the record number will change, push the record number as it
    ** will be after the update. (The old record number is currently
    ** on top of the stack.)
    */
    if( chngRowid ){
      sqlite3ExprCode(pParse, pRowidExpr, 0);

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531

4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
....
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561

4562
4563
4564
4565
4566
4567
4568
**
** 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.675 2008/01/04 13:24:29 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
................................................................................
  pTos->enc = SQLITE_UTF8;
  sqlite3VdbeChangeEncoding(pTos, encoding);
  sqlite3_free(aRoot);
  break;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

/* Opcode: FifoWrite * * *
**
** Write the integer on the top of the stack into the Fifo.
*/
case OP_FifoWrite: {        /* no-push */
  assert( pTos>=p->aStack );

  sqlite3VdbeMemIntegerify(pTos);
  if( sqlite3VdbeFifoPush(&p->sFifo, pTos->u.i)==SQLITE_NOMEM ){
    goto no_mem;
  }
  assert( (pTos->flags & MEM_Dyn)==0 );
  pTos--;
  break;
}

/* Opcode: FifoRead P1 P2 *
**
** Attempt to read a single integer from the Fifo. If P1 is zero,
** push the result onto the stack. Otherwise, store the read integer 
................................................................................
*/
case OP_FifoRead: {
  i64 v;
  CHECK_FOR_INTERRUPT;
  if( sqlite3VdbeFifoPop(&p->sFifo, &v)==SQLITE_DONE ){
    pc = pOp->p2 - 1;
  }else{
    Mem *pOut;
    if( pOp->p1 ){
      pOut = &p->aMem[pOp->p1];
    }else{
      pOut = ++pTos;
    }

    sqlite3VdbeMemSetInt64(pOut, v);
  }
  break;
}

#ifndef SQLITE_OMIT_TRIGGER
/* Opcode: ContextPush * * * 







|







 







|

|


|
>
|
|


<
<







 







<
<
|
<
<
<
>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536


4537
4538
4539
4540
4541
4542
4543
....
4548
4549
4550
4551
4552
4553
4554


4555



4556
4557
4558
4559
4560
4561
4562
4563
**
** 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.676 2008/01/04 13:57:26 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
................................................................................
  pTos->enc = SQLITE_UTF8;
  sqlite3VdbeChangeEncoding(pTos, encoding);
  sqlite3_free(aRoot);
  break;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

/* Opcode: FifoWrite P1 * *
**
** Write the integer from memory cell P1 into the Fifo.
*/
case OP_FifoWrite: {        /* no-push */
  Mem *pReg = &p->aMem[pOp->p1];
  assert( pOp->p1>0 && pOp->p1<=p->nMem );
  sqlite3VdbeMemIntegerify(pReg);
  if( sqlite3VdbeFifoPush(&p->sFifo, pReg->u.i)==SQLITE_NOMEM ){
    goto no_mem;
  }


  break;
}

/* Opcode: FifoRead P1 P2 *
**
** Attempt to read a single integer from the Fifo. If P1 is zero,
** push the result onto the stack. Otherwise, store the read integer 
................................................................................
*/
case OP_FifoRead: {
  i64 v;
  CHECK_FOR_INTERRUPT;
  if( sqlite3VdbeFifoPop(&p->sFifo, &v)==SQLITE_DONE ){
    pc = pOp->p2 - 1;
  }else{


    Mem *pOut = &p->aMem[pOp->p1];



    assert( pOp->p1>0 && pOp->p1<=p->nMem );
    sqlite3VdbeMemSetInt64(pOut, v);
  }
  break;
}

#ifndef SQLITE_OMIT_TRIGGER
/* Opcode: ContextPush * * *