Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fixed behaviour of last_insert_rowid() with triggers and add last_statement_change_count() function that works correctly with triggers. (CVS 1251) |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
3383413a53bff0fef0765144de3bb9a2 |
User & Date: | rdc 2004-02-20 22:53:39 |
Context
2004-02-20
| ||
22:54 | Fixed behaviour of last_insert_rowid() with triggers and add last_statement_change_count() function that works correctly with triggers. (CVS 1252) check-in: 6734c923 user: rdc tags: trunk | |
22:53 | Fixed behaviour of last_insert_rowid() with triggers and add last_statement_change_count() function that works correctly with triggers. (CVS 1251) check-in: 3383413a user: rdc tags: trunk | |
14:50 | The name of a result column is now the name of column it originated from, by default. This can be turned off with PRAGMA short_column_names=OFF. This is to be more like PostgreSQL. More testing needed. (CVS 1250) check-in: 574dd444 user: drh tags: trunk | |
Changes
Changes to publish.sh.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
sqliteFree sqliteRealloc sqlite_set_authorizer sqlite_trace sqlite_compile sqlite_step sqlite_finalize END_OF_FILE i386-mingw32msvc-dllwrap \ --def sqlite.def -v --export-all \ --driver-name i386-mingw32msvc-gcc \ --dlltool-name i386-mingw32msvc-dlltool \ --as i386-mingw32msvc-as \ --target i386-mingw32 \ |
> > > |
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
sqliteFree sqliteRealloc sqlite_set_authorizer sqlite_trace sqlite_compile sqlite_step sqlite_finalize sqlite_reset sqlite_bind sqlite_last_statement_changes END_OF_FILE i386-mingw32msvc-dllwrap \ --def sqlite.def -v --export-all \ --driver-name i386-mingw32msvc-gcc \ --dlltool-name i386-mingw32msvc-dlltool \ --as i386-mingw32msvc-as \ --target i386-mingw32 \ |
Changes to src/delete.c.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ... 295 296 297 298 299 300 301 302 303 304 305 306 307 308 ... 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 |
** 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 DELETE FROM statements. ** ** $Id: delete.c,v 1.59 2004/02/16 03:44:02 drh 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. ................................................................................ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); } sqliteVdbeAddOp(v, OP_Close, iCur, 0); pParse->nTab = iCur; } } sqliteEndWriteOperation(pParse); /* ** Return the number of rows that were deleted. */ if( db->flags & SQLITE_CountRows ){ sqliteVdbeAddOp(v, OP_ColumnName, 0, 1); ................................................................................ Table *pTab, /* Table containing the row to be deleted */ int iCur, /* Cursor number for the table */ int count /* Increment the row change counter */ ){ int addr; addr = sqliteVdbeAddOp(v, OP_NotExists, iCur, 0); sqliteGenerateRowIndexDelete(db, v, pTab, iCur, 0); sqliteVdbeAddOp(v, OP_Delete, iCur, count); sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v)); } /* ** This routine generates VDBE code that causes the deletion of all ** index entries associated with a single row of a single table. ** |
| > | > |
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ... 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 ... 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
** 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 DELETE FROM statements. ** ** $Id: delete.c,v 1.60 2004/02/20 22:53:39 rdc 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. ................................................................................ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); } sqliteVdbeAddOp(v, OP_Close, iCur, 0); pParse->nTab = iCur; } } sqliteVdbeAddOp(v, OP_SetCounts, 0, 0); sqliteEndWriteOperation(pParse); /* ** Return the number of rows that were deleted. */ if( db->flags & SQLITE_CountRows ){ sqliteVdbeAddOp(v, OP_ColumnName, 0, 1); ................................................................................ Table *pTab, /* Table containing the row to be deleted */ int iCur, /* Cursor number for the table */ int count /* Increment the row change counter */ ){ int addr; addr = sqliteVdbeAddOp(v, OP_NotExists, iCur, 0); sqliteGenerateRowIndexDelete(db, v, pTab, iCur, 0); sqliteVdbeAddOp(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0) | OPFLAG_CSCHANGE); sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v)); } /* ** This routine generates VDBE code that causes the deletion of all ** index entries associated with a single row of a single table. ** |
Changes to src/func.c.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ... 204 205 206 207 208 209 210 211 212 213 214 215 216 217 ... 609 610 611 612 613 614 615 616 617 618 619 620 621 622 |
** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** ** $Id: func.c,v 1.39 2004/02/11 09:46:32 drh Exp $ */ #include <ctype.h> #include <math.h> #include <stdlib.h> #include <assert.h> #include "sqliteInt.h" #include "os.h" ................................................................................ ** Implementation of the last_insert_rowid() SQL function. The return ** value is the same as the sqlite_last_insert_rowid() API function. */ static void last_insert_rowid(sqlite_func *context, int arg, const char **argv){ sqlite *db = sqlite_user_data(context); sqlite_set_result_int(context, sqlite_last_insert_rowid(db)); } /* ** Implementation of the like() SQL function. This function implements ** the build-in LIKE operator. The first argument to the function is the ** string and the second argument is the pattern. So, the SQL statements: ** ** A LIKE B ................................................................................ if( aFuncs[i].xFunc ){ sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType); } } sqlite_create_function(db, "last_insert_rowid", 0, last_insert_rowid, db); sqlite_function_type(db, "last_insert_rowid", SQLITE_NUMERIC); for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){ sqlite_create_aggregate(db, aAggs[i].zName, aAggs[i].nArg, aAggs[i].xStep, aAggs[i].xFinalize, 0); sqlite_function_type(db, aAggs[i].zName, aAggs[i].dataType); } sqliteRegisterDateTimeFunctions(db); } |
| > > > > > > > > > > > > > > > > |
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ... 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 ... 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 |
** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** ** $Id: func.c,v 1.40 2004/02/20 22:53:39 rdc Exp $ */ #include <ctype.h> #include <math.h> #include <stdlib.h> #include <assert.h> #include "sqliteInt.h" #include "os.h" ................................................................................ ** Implementation of the last_insert_rowid() SQL function. The return ** value is the same as the sqlite_last_insert_rowid() API function. */ static void last_insert_rowid(sqlite_func *context, int arg, const char **argv){ sqlite *db = sqlite_user_data(context); sqlite_set_result_int(context, sqlite_last_insert_rowid(db)); } static void change_count(sqlite_func *context, int arg, const char **argv){ sqlite *db = sqlite_user_data(context); sqlite_set_result_int(context, sqlite_changes(db)); } static void last_statement_change_count(sqlite_func *context, int arg, const char **argv){ sqlite *db = sqlite_user_data(context); sqlite_set_result_int(context, sqlite_last_statement_changes(db)); } /* ** Implementation of the like() SQL function. This function implements ** the build-in LIKE operator. The first argument to the function is the ** string and the second argument is the pattern. So, the SQL statements: ** ** A LIKE B ................................................................................ if( aFuncs[i].xFunc ){ sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType); } } sqlite_create_function(db, "last_insert_rowid", 0, last_insert_rowid, db); sqlite_function_type(db, "last_insert_rowid", SQLITE_NUMERIC); sqlite_create_function(db, "change_count", 0, change_count, db); sqlite_function_type(db, "change_count", SQLITE_NUMERIC); sqlite_create_function(db, "last_statement_change_count", 0, last_statement_change_count, db); sqlite_function_type(db, "last_statement_change_count", SQLITE_NUMERIC); for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){ sqlite_create_aggregate(db, aAggs[i].zName, aAggs[i].nArg, aAggs[i].xStep, aAggs[i].xFinalize, 0); sqlite_function_type(db, aAggs[i].zName, aAggs[i].dataType); } sqliteRegisterDateTimeFunctions(db); } |
Changes to src/insert.c.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ... 531 532 533 534 535 536 537 538 539 540 541 542 543 544 ... 902 903 904 905 906 907 908 909 910 911 912 913 |
** 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 INSERT statements in SQLite. ** ** $Id: insert.c,v 1.91 2004/02/16 03:44:02 drh Exp $ */ #include "sqliteInt.h" /* ** This routine is call to handle SQL of the following forms: ** ** insert into TABLE (IDLIST) values(EXPRLIST) ................................................................................ /* Close all tables opened */ sqliteVdbeAddOp(v, OP_Close, base, 0); for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ sqliteVdbeAddOp(v, OP_Close, idx+base, 0); } } sqliteEndWriteOperation(pParse); /* ** Return the number of rows inserted. */ if( db->flags & SQLITE_CountRows ){ sqliteVdbeAddOp(v, OP_ColumnName, 0, 1); ................................................................................ } sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); if( newIdx>=0 ){ sqliteVdbeAddOp(v, OP_Dup, 1, 0); sqliteVdbeAddOp(v, OP_Dup, 1, 0); sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0); } sqliteVdbeAddOp(v, OP_PutIntKey, base, pParse->trigStack?0:1); if( isUpdate && recnoChng ){ sqliteVdbeAddOp(v, OP_Pop, 1, 0); } } |
| > | > > |
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ... 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 ... 903 904 905 906 907 908 909 910 911 912 913 914 915 916 |
** 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 INSERT statements in SQLite. ** ** $Id: insert.c,v 1.92 2004/02/20 22:53:39 rdc Exp $ */ #include "sqliteInt.h" /* ** This routine is call to handle SQL of the following forms: ** ** insert into TABLE (IDLIST) values(EXPRLIST) ................................................................................ /* Close all tables opened */ sqliteVdbeAddOp(v, OP_Close, base, 0); for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ sqliteVdbeAddOp(v, OP_Close, idx+base, 0); } } sqliteVdbeAddOp(v, OP_SetCounts, 0, 0); sqliteEndWriteOperation(pParse); /* ** Return the number of rows inserted. */ if( db->flags & SQLITE_CountRows ){ sqliteVdbeAddOp(v, OP_ColumnName, 0, 1); ................................................................................ } sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); if( newIdx>=0 ){ sqliteVdbeAddOp(v, OP_Dup, 1, 0); sqliteVdbeAddOp(v, OP_Dup, 1, 0); sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0); } sqliteVdbeAddOp(v, OP_PutIntKey, base, (pParse->trigStack?0:OPFLAG_NCHANGE) | (isUpdate?0:OPFLAG_LASTROWID) | OPFLAG_CSCHANGE); if( isUpdate && recnoChng ){ sqliteVdbeAddOp(v, OP_Pop, 1, 0); } } |
Changes to src/main.c.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
540
541
542
543
544
545
546
547
548
549
550
551
552
553
|
** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.157 2004/02/20 14:50:58 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** A pointer to this structure is used to communicate information ................................................................................ /* ** Return the number of changes in the most recent call to sqlite_exec(). */ int sqlite_changes(sqlite *db){ return db->nChange; } /* ** Close an existing SQLite database */ void sqlite_close(sqlite *db){ HashElem *i; int j; |
|
>
>
>
>
|
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
|
** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.158 2004/02/20 22:53:39 rdc Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** A pointer to this structure is used to communicate information ................................................................................ /* ** Return the number of changes in the most recent call to sqlite_exec(). */ int sqlite_changes(sqlite *db){ return db->nChange; } int sqlite_last_statement_changes(sqlite *db){ return db->lsChange; } /* ** Close an existing SQLite database */ void sqlite_close(sqlite *db){ HashElem *i; int j; |
Changes to src/sqliteInt.h.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ... 305 306 307 308 309 310 311 312 313 314 315 316 317 318 ... 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 ... 903 904 905 906 907 908 909 910 911 912 913 914 915 916 |
** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.214 2004/02/20 14:50:58 drh Exp $ */ #include "config.h" #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" ................................................................................ ** file_format==4 Version 2.7.0. Add support for separate numeric and ** text datatypes. ** ** The sqlite.temp_store determines where temporary database files ** are stored. If 1, then a file is created to hold those tables. If ** 2, then they are held in memory. 0 means use the default value in ** the TEMP_STORE macro. */ struct sqlite { int nDb; /* Number of backends currently in use */ Db *aDb; /* All backends */ Db aDbStatic[2]; /* Static space for the 2 default backends */ int flags; /* Miscellanous flags. See below */ u8 file_format; /* What file format version is this database? */ ................................................................................ int cache_size; /* Number of pages to use in the cache */ int nTable; /* Number of tables in the database */ void *pBusyArg; /* 1st Argument to the busy callback */ int (*xBusyCallback)(void *,const char*,int); /* The busy callback */ void *pCommitArg; /* Argument to xCommitCallback() */ int (*xCommitCallback)(void*);/* Invoked at every commit. */ Hash aFunc; /* All functions that can be in SQL exprs */ int lastRowid; /* ROWID of most recent insert */ int priorNewRowid; /* Last randomly generated ROWID */ int magic; /* Magic number for detect library misuse */ int nChange; /* Number of rows changed */ struct sqliteInitInfo { /* Information used during initialization */ int iDb; /* When back is being initialized */ int newTnum; /* Rootpage of table being initialized */ u8 busy; /* TRUE if currently initializing */ } init; struct Vdbe *pVdbe; /* List of active virtual machines */ void (*xTrace)(void*,const char*); /* Trace function */ ................................................................................ ** to save the Parse.zAuthContext value so that it can be restored later. */ struct AuthContext { const char *zAuthContext; /* Put saved Parse.zAuthContext here */ Parse *pParse; /* The Parse structure */ }; /* * Each trigger present in the database schema is stored as an instance of * struct Trigger. * * Pointers to instances of struct Trigger are stored in two ways. * 1. In the "trigHash" hash table (part of the sqlite* that represents the * database). This allows Trigger structures to be retrieved by name. |
| > > > > > > > > > > > > > > > > > > | | > > > > > > > > > |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ... 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 ... 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 ... 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 |
** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.215 2004/02/20 22:53:39 rdc Exp $ */ #include "config.h" #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" ................................................................................ ** file_format==4 Version 2.7.0. Add support for separate numeric and ** text datatypes. ** ** The sqlite.temp_store determines where temporary database files ** are stored. If 1, then a file is created to hold those tables. If ** 2, then they are held in memory. 0 means use the default value in ** the TEMP_STORE macro. ** ** The sqlite.lastRowid records the last insert rowid generated by an ** insert statement. Inserts on views do not affect its value. Each ** trigger has its own context, so that lastRowid can be updated inside ** triggers as usual. The previous value will be restored once the trigger ** exits. Upon entering a before or instead of trigger, lastRowid is no ** longer (since after version 2.8.12) reset to -1. ** ** The sqlite.nChange does not count changes within triggers and keeps no ** context. It is reset at start of sqlite_exec. ** The sqlite.lsChange represents the number of changes made by the last ** insert, update, or delete statement. It remains constant throughout the ** length of a statement and is then updated by OP_SetCounts. It keeps a ** context stack just like lastRowid so that the count of changes ** within a trigger is not seen outside the trigger. Changes to views do not ** affect the value of lsChange. ** The sqlite.csChange keeps track of the number of current changes (since ** the last statement) and is used to update sqlite_lsChange. */ struct sqlite { int nDb; /* Number of backends currently in use */ Db *aDb; /* All backends */ Db aDbStatic[2]; /* Static space for the 2 default backends */ int flags; /* Miscellanous flags. See below */ u8 file_format; /* What file format version is this database? */ ................................................................................ int cache_size; /* Number of pages to use in the cache */ int nTable; /* Number of tables in the database */ void *pBusyArg; /* 1st Argument to the busy callback */ int (*xBusyCallback)(void *,const char*,int); /* The busy callback */ void *pCommitArg; /* Argument to xCommitCallback() */ int (*xCommitCallback)(void*);/* Invoked at every commit. */ Hash aFunc; /* All functions that can be in SQL exprs */ int lastRowid; /* ROWID of most recent insert (see above) */ int priorNewRowid; /* Last randomly generated ROWID */ int magic; /* Magic number for detect library misuse */ int nChange; /* Number of rows changed (see above) */ int lsChange; /* Last statement change count (see above) */ int csChange; /* Current statement change count (see above) */ struct sqliteInitInfo { /* Information used during initialization */ int iDb; /* When back is being initialized */ int newTnum; /* Rootpage of table being initialized */ u8 busy; /* TRUE if currently initializing */ } init; struct Vdbe *pVdbe; /* List of active virtual machines */ void (*xTrace)(void*,const char*); /* Trace function */ ................................................................................ ** to save the Parse.zAuthContext value so that it can be restored later. */ struct AuthContext { const char *zAuthContext; /* Put saved Parse.zAuthContext here */ Parse *pParse; /* The Parse structure */ }; /* ** Bitfield flags for P2 value in OP_PutIntKey and OP_Delete */ #define OPFLAG_NCHANGE 1 /* Set to update db->nChange */ #define OPFLAG_LASTROWID 2 /* Set to update db->lastRowid */ #define OPFLAG_CSCHANGE 4 /* Set to update db->csChange */ /* * Each trigger present in the database schema is stored as an instance of * struct Trigger. * * Pointers to instances of struct Trigger are stored in two ways. * 1. In the "trigHash" hash table (part of the sqlite* that represents the * database). This allows Trigger structures to be retrieved by name. |
Changes to src/trigger.c.
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 |
sqliteFree(pTriggerStack); sqliteExprDelete(whenExpr); return 1; } sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1); sqliteExprDelete(whenExpr); codeTriggerProgram(pParse, pTrigger->step_list, orconf); /* Pop the entry off the trigger stack */ pParse->trigStack = pParse->trigStack->pNext; sqliteAuthContextPop(&sContext); sqliteFree(pTriggerStack); sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger); } pTrigger = pTrigger->pNext; } return 0; } |
> > |
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 |
sqliteFree(pTriggerStack); sqliteExprDelete(whenExpr); return 1; } sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1); sqliteExprDelete(whenExpr); sqliteVdbeAddOp(pParse->pVdbe, OP_ContextPush, 0, 0); codeTriggerProgram(pParse, pTrigger->step_list, orconf); sqliteVdbeAddOp(pParse->pVdbe, OP_ContextPop, 0, 0); /* Pop the entry off the trigger stack */ pParse->trigStack = pParse->trigStack->pNext; sqliteAuthContextPop(&sContext); sqliteFree(pTriggerStack); sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger); } pTrigger = pTrigger->pNext; } return 0; } |
Changes to src/update.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
426
427
428
429
430
431
432
433
434
435
436
437
438
439
|
** 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.68 2004/02/16 03:44:02 drh Exp $ */ #include "sqliteInt.h" /* ** Process an UPDATE statement. ** ** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL; ................................................................................ sqliteVdbeAddOp(v, OP_Close, iCur, 0); pParse->nTab = iCur; }else{ sqliteVdbeAddOp(v, OP_Close, newIdx, 0); sqliteVdbeAddOp(v, OP_Close, oldIdx, 0); } sqliteEndWriteOperation(pParse); /* ** Return the number of rows that were changed. */ if( db->flags & SQLITE_CountRows && !pParse->trigStack ){ sqliteVdbeAddOp(v, OP_ColumnName, 0, 1); |
|
>
|
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
|
** 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.69 2004/02/20 22:53:39 rdc Exp $ */ #include "sqliteInt.h" /* ** Process an UPDATE statement. ** ** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL; ................................................................................ sqliteVdbeAddOp(v, OP_Close, iCur, 0); pParse->nTab = iCur; }else{ sqliteVdbeAddOp(v, OP_Close, newIdx, 0); sqliteVdbeAddOp(v, OP_Close, oldIdx, 0); } sqliteVdbeAddOp(v, OP_SetCounts, 0, 0); sqliteEndWriteOperation(pParse); /* ** Return the number of rows that were changed. */ if( db->flags & SQLITE_CountRows && !pParse->trigStack ){ sqliteVdbeAddOp(v, OP_ColumnName, 0, 1); |
Changes to src/vdbe.c.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 .... 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 .... 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 .... 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 .... 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 |
** ** 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.265 2004/02/16 03:44:02 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* ................................................................................ ** ** Write an entry into the table of cursor P1. A new entry is ** created if it doesn't already exist or the data for an existing ** entry is overwritten. The data is the value on the top of the ** stack. The key is the next value down on the stack. The key must ** be an integer. The stack is popped twice by this instruction. ** ** If P2==1 then the row change count is incremented. If P2==0 the ** row change count is unmodified. The rowid is stored for subsequent ** return by the sqlite_last_insert_rowid() function if P2 is 1. */ /* Opcode: PutStrKey P1 * * ** ** Write an entry into the table of cursor P1. A new entry is ** created if it doesn't already exist or the data for an existing ** entry is overwritten. The data is the value on the top of the ** stack. The key is the next value down on the stack. The key must ................................................................................ nKey = pNos->n; zKey = pNos->z; }else{ assert( pNos->flags & MEM_Int ); nKey = sizeof(int); iKey = intToKey(pNos->i); zKey = (char*)&iKey; if( pOp->p2 ){ db->nChange++; db->lastRowid = pNos->i; } if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){ pC->nextRowidValid = 0; } } if( pTos->flags & MEM_Null ){ pTos->z = 0; pTos->n = 0; ................................................................................ ** 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. ** ** If P1 is a pseudo-table, then this instruction is a no-op. */ case OP_Delete: { int i = pOp->p1; Cursor *pC; assert( i>=0 && i<p->nCursor ); pC = &p->aCsr[i]; if( pC->pCursor!=0 ){ sqliteVdbeCursorMoveto(pC); rc = sqliteBtreeDelete(pC->pCursor); pC->nextRowidValid = 0; } if( pOp->p2 ) db->nChange++; break; } /* Opcode: KeyAsData P1 P2 * ** ** Turn the key-as-data mode for cursor P1 either on (if P2==1) or ** off (if P2==0). In key-as-data mode, the OP_Column opcode pulls ................................................................................ p->keylistStack[p->keylistStackDepth] = 0; if( p->keylistStackDepth == 0 ){ sqliteFree(p->keylistStack); p->keylistStack = 0; } break; } /* Opcode: SortPut * * * ** ** The TOS is the key and the NOS is the data. Pop both from the stack ** and put them on the sorter. The key and data should have been ** made using SortMakeKey and SortMakeRec, respectively. */ |
| | | > > | > < | | < > | | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 .... 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 .... 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 .... 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 .... 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 |
** ** 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.266 2004/02/20 22:53:39 rdc Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* ................................................................................ ** ** Write an entry into the table of cursor P1. A new entry is ** created if it doesn't already exist or the data for an existing ** entry is overwritten. The data is the value on the top of the ** stack. The key is the next value down on the stack. The key must ** be an integer. The stack is popped twice by this instruction. ** ** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is ** incremented (otherwise not). If the OPFLAG_CSCHANGE flag is set, ** then the current statement change count is incremented (otherwise not). ** If the OPFLAG_LASTROWID flag of P2 is set, then rowid is ** stored for subsequent return by the sqlite_last_insert_rowid() function ** (otherwise it's unmodified). */ /* Opcode: PutStrKey P1 * * ** ** Write an entry into the table of cursor P1. A new entry is ** created if it doesn't already exist or the data for an existing ** entry is overwritten. The data is the value on the top of the ** stack. The key is the next value down on the stack. The key must ................................................................................ nKey = pNos->n; zKey = pNos->z; }else{ assert( pNos->flags & MEM_Int ); nKey = sizeof(int); iKey = intToKey(pNos->i); zKey = (char*)&iKey; if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++; if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i; if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++; if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){ pC->nextRowidValid = 0; } } if( pTos->flags & MEM_Null ){ pTos->z = 0; pTos->n = 0; ................................................................................ ** 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. ** ** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is ** incremented (otherwise not). If OPFLAG_CSCHANGE flag is set, ** then the current statement change count is incremented (otherwise not). ** ** If P1 is a pseudo-table, then this instruction is a no-op. */ case OP_Delete: { int i = pOp->p1; Cursor *pC; assert( i>=0 && i<p->nCursor ); pC = &p->aCsr[i]; if( pC->pCursor!=0 ){ sqliteVdbeCursorMoveto(pC); rc = sqliteBtreeDelete(pC->pCursor); pC->nextRowidValid = 0; } if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++; if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++; break; } /* Opcode: SetCounts * * * ** ** Called at end of statement. Updates lsChange (last statement change count) ** and resets csChange (current statement change count) to 0. */ case OP_SetCounts: { db->lsChange=db->csChange; db->csChange=0; break; } /* Opcode: KeyAsData P1 P2 * ** ** Turn the key-as-data mode for cursor P1 either on (if P2==1) or ** off (if P2==0). In key-as-data mode, the OP_Column opcode pulls ................................................................................ p->keylistStack[p->keylistStackDepth] = 0; if( p->keylistStackDepth == 0 ){ sqliteFree(p->keylistStack); p->keylistStack = 0; } break; } /* Opcode: ContextPush * * * ** ** Save the current Vdbe context such that it can be restored by a ContextPop ** opcode. The context stores the last insert row id, the last statement change ** count, and the current statement change count. */ case OP_ContextPush: { p->contextStackDepth++; assert(p->contextStackDepth > 0); p->contextStack = sqliteRealloc(p->contextStack, sizeof(Context) * p->contextStackDepth); if( p->contextStack==0 ) goto no_mem; p->contextStack[p->contextStackDepth - 1].lastRowid = p->db->lastRowid; p->contextStack[p->contextStackDepth - 1].lsChange = p->db->lsChange; p->contextStack[p->contextStackDepth - 1].csChange = p->db->csChange; break; } /* Opcode: ContextPop * * * ** ** Restore the Vdbe context to the state it was in when contextPush was last ** executed. The context stores the last insert row id, the last statement ** change count, and the current statement change count. */ case OP_ContextPop: { assert(p->contextStackDepth > 0); p->contextStackDepth--; p->db->lastRowid = p->contextStack[p->contextStackDepth].lastRowid; p->db->lsChange = p->contextStack[p->contextStackDepth].lsChange; p->db->csChange = p->contextStack[p->contextStackDepth].csChange; if( p->contextStackDepth == 0 ){ sqliteFree(p->contextStack); p->contextStack = 0; } break; } /* Opcode: SortPut * * * ** ** The TOS is the key and the NOS is the data. Pop both from the stack ** and put them on the sorter. The key and data should have been ** made using SortMakeKey and SortMakeRec, respectively. */ |
Changes to src/vdbeInt.h.
203
204
205
206
207
208
209
210
211
212
213
214
215
216
...
246
247
248
249
250
251
252
253
254
255
256
257
258
259
|
int nKey; /* Number of slots in aKey[] */
int nUsed; /* Next unwritten slot in aKey[] */
int nRead; /* Next unread slot in aKey[] */
Keylist *pNext; /* Next block of keys */
int aKey[1]; /* One or more keys. Extra space allocated as needed */
};
/*
** An instance of the virtual machine. This structure contains the complete
** state of the virtual machine.
**
** The "sqlite_vm" structure pointer that is returned by sqlite_compile()
** is really a pointer to an instance of this structure.
*/
................................................................................
Agg agg; /* Aggregate information */
int nSet; /* Number of sets allocated */
Set *aSet; /* An array of sets */
int nCallback; /* Number of callbacks invoked so far */
Keylist *pList; /* A list of ROWIDs */
int keylistStackDepth; /* The size of the "keylist" stack */
Keylist **keylistStack; /* The stack used by opcodes ListPush & ListPop */
int pc; /* The program counter */
int rc; /* Value to return */
unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */
int errorAction; /* Recovery action to do in case of an error */
int undoTransOnError; /* If error, either ROLLBACK or COMMIT */
int inTempTrans; /* True if temp database is transactioned */
int returnStack[100]; /* Return address stack for OP_Gosub & OP_Return */
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
...
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
|
int nKey; /* Number of slots in aKey[] */ int nUsed; /* Next unwritten slot in aKey[] */ int nRead; /* Next unread slot in aKey[] */ Keylist *pNext; /* Next block of keys */ int aKey[1]; /* One or more keys. Extra space allocated as needed */ }; /* ** A Context stores the last insert rowid, the last statement change count, ** and the current statement change count (i.e. changes since last statement). ** Elements of Context structure type make up the ContextStack, which is ** updated by the ContextPush and ContextPop opcodes (used by triggers) */ typedef struct Context Context; struct Context { int lastRowid; /* Last insert rowid (from db->lastRowid) */ int lsChange; /* Last statement change count (from db->lsChange) */ int csChange; /* Current statement change count (from db->csChange) */ }; /* ** An instance of the virtual machine. This structure contains the complete ** state of the virtual machine. ** ** The "sqlite_vm" structure pointer that is returned by sqlite_compile() ** is really a pointer to an instance of this structure. */ ................................................................................ Agg agg; /* Aggregate information */ int nSet; /* Number of sets allocated */ Set *aSet; /* An array of sets */ int nCallback; /* Number of callbacks invoked so far */ Keylist *pList; /* A list of ROWIDs */ int keylistStackDepth; /* The size of the "keylist" stack */ Keylist **keylistStack; /* The stack used by opcodes ListPush & ListPop */ int contextStackDepth; /* The size of the "context" stack */ Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/ int pc; /* The program counter */ int rc; /* Value to return */ unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */ int errorAction; /* Recovery action to do in case of an error */ int undoTransOnError; /* If error, either ROLLBACK or COMMIT */ int inTempTrans; /* True if temp database is transactioned */ int returnStack[100]; /* Return address stack for OP_Gosub & OP_Return */ |