Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Reference count Table structures so that they are not deallocated too soon. Ticket #1210. (CVS 2498) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
e73d25c7419d580c47925494621df26d |
User & Date: | drh 2005-06-06 21:19:57.000 |
Context
2005-06-07
| ||
01:43 | Do not open a statement journal unless absolutely necessary. (CVS 2499) (check-in: 989573a53b user: drh tags: trunk) | |
2005-06-06
| ||
21:19 | Reference count Table structures so that they are not deallocated too soon. Ticket #1210. (CVS 2498) (check-in: e73d25c741 user: drh tags: trunk) | |
17:54 | Return SQLITE_MISUSE when passing a NULL pointer into sqlite3_bind routines. Ticket #1219. (CVS 2497) (check-in: 12c32f139b user: drh tags: trunk) | |
Changes
Changes to src/alter.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** 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 used to generate VDBE code ** that implements the ALTER TABLE command. ** | | | 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 used to generate VDBE code ** that implements the ALTER TABLE command. ** ** $Id: alter.c,v 1.7 2005/06/06 21:19:57 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** The code in this file only exists if we are not omitting the ** ALTER TABLE logic from the build. |
︙ | ︙ | |||
534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 | Column *pCol = &pNew->aCol[i]; pCol->zName = sqliteStrDup(pCol->zName); pCol->zType = 0; pCol->pDflt = 0; } pNew->iDb = iDb; pNew->addColOffset = pTab->addColOffset; /* Begin a transaction and increment the schema cookie. */ sqlite3BeginWriteOperation(pParse, 0, iDb); v = sqlite3GetVdbe(pParse); if( !v ) goto exit_begin_add_column; sqlite3ChangeCookie(pParse->db, v, iDb); exit_begin_add_column: sqlite3SrcListDelete(pSrc); return; } #endif /* SQLITE_ALTER_TABLE */ | > | 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 | Column *pCol = &pNew->aCol[i]; pCol->zName = sqliteStrDup(pCol->zName); pCol->zType = 0; pCol->pDflt = 0; } pNew->iDb = iDb; pNew->addColOffset = pTab->addColOffset; pNew->nRef = 1; /* Begin a transaction and increment the schema cookie. */ sqlite3BeginWriteOperation(pParse, 0, iDb); v = sqlite3GetVdbe(pParse); if( !v ) goto exit_begin_add_column; sqlite3ChangeCookie(pParse->db, v, iDb); exit_begin_add_column: sqlite3SrcListDelete(pSrc); return; } #endif /* SQLITE_ALTER_TABLE */ |
Changes to src/build.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** ** $Id: build.c,v 1.325 2005/06/06 21:19:57 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. |
︙ | ︙ | |||
422 423 424 425 426 427 428 429 430 431 432 433 434 435 | ** unlinked. */ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ Index *pIndex, *pNext; FKey *pFKey, *pNextFKey; if( pTable==0 ) return; /* Delete all indices associated with this table */ for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ pNext = pIndex->pNext; assert( pIndex->iDb==pTable->iDb || (pTable->iDb==0 && pIndex->iDb==1) ); sqliteDeleteIndex(db, pIndex); | > > > > > > > | 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 | ** unlinked. */ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ Index *pIndex, *pNext; FKey *pFKey, *pNextFKey; if( pTable==0 ) return; /* Do not delete the table until the reference count reaches zero. */ pTable->nRef--; if( pTable->nRef>0 ){ return; } assert( pTable->nRef==0 ); /* Delete all indices associated with this table */ for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ pNext = pIndex->pNext; assert( pIndex->iDb==pTable->iDb || (pTable->iDb==0 && pIndex->iDb==1) ); sqliteDeleteIndex(db, pIndex); |
︙ | ︙ | |||
725 726 727 728 729 730 731 732 733 734 735 736 737 738 | } pTable->zName = zName; pTable->nCol = 0; pTable->aCol = 0; pTable->iPKey = -1; pTable->pIndex = 0; pTable->iDb = iDb; if( pParse->pNewTable ) sqlite3DeleteTable(db, pParse->pNewTable); pParse->pNewTable = pTable; /* If this is the magic sqlite_sequence table used by autoincrement, ** then record a pointer to this table in the main database structure ** so that INSERT can find the table easily. */ | > | 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 | } pTable->zName = zName; pTable->nCol = 0; pTable->aCol = 0; pTable->iPKey = -1; pTable->pIndex = 0; pTable->iDb = iDb; pTable->nRef = 1; if( pParse->pNewTable ) sqlite3DeleteTable(db, pParse->pNewTable); pParse->pNewTable = pTable; /* If this is the magic sqlite_sequence table used by autoincrement, ** then record a pointer to this table in the main database structure ** so that INSERT can find the table easily. */ |
︙ | ︙ | |||
2581 2582 2583 2584 2585 2586 2587 | int i; struct SrcList_item *pItem; if( pList==0 ) return; for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){ sqliteFree(pItem->zDatabase); sqliteFree(pItem->zName); sqliteFree(pItem->zAlias); | < | < | 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 | int i; struct SrcList_item *pItem; if( pList==0 ) return; for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){ sqliteFree(pItem->zDatabase); sqliteFree(pItem->zName); sqliteFree(pItem->zAlias); sqlite3DeleteTable(0, pItem->pTab); sqlite3SelectDelete(pItem->pSelect); sqlite3ExprDelete(pItem->pOn); sqlite3IdListDelete(pItem->pUsing); } sqliteFree(pList); } |
︙ | ︙ |
Changes to src/delete.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** 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. ** | | > > > > | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | ** 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.105 2005/06/06 21:19:57 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. */ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ Table *pTab = 0; int i; struct SrcList_item *pItem; for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){ pTab = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase); sqlite3DeleteTable(pParse->db, pItem->pTab); pItem->pTab = pTab; if( pTab ){ pTab->nRef++; } } return pTab; } /* ** Check to make sure the given table is writable. If it is not ** writable, generate an error message and return 1. If it is |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** 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. ** | | | 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.205 2005/06/06 21:19:57 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Return the 'affinity' of the expression pExpr if any. ** |
︙ | ︙ | |||
470 471 472 473 474 475 476 477 478 479 480 481 | nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); pNew = sqliteMallocRaw( nByte ); if( pNew==0 ) return 0; pNew->nSrc = pNew->nAlloc = p->nSrc; for(i=0; i<p->nSrc; i++){ struct SrcList_item *pNewItem = &pNew->a[i]; struct SrcList_item *pOldItem = &p->a[i]; pNewItem->zDatabase = sqliteStrDup(pOldItem->zDatabase); pNewItem->zName = sqliteStrDup(pOldItem->zName); pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias); pNewItem->jointype = pOldItem->jointype; pNewItem->iCursor = pOldItem->iCursor; | > | | | | 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 | nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); pNew = sqliteMallocRaw( nByte ); if( pNew==0 ) return 0; pNew->nSrc = pNew->nAlloc = p->nSrc; for(i=0; i<p->nSrc; i++){ struct SrcList_item *pNewItem = &pNew->a[i]; struct SrcList_item *pOldItem = &p->a[i]; Table *pTab; pNewItem->zDatabase = sqliteStrDup(pOldItem->zDatabase); pNewItem->zName = sqliteStrDup(pOldItem->zName); pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias); pNewItem->jointype = pOldItem->jointype; pNewItem->iCursor = pOldItem->iCursor; pTab = pNewItem->pTab = pOldItem->pTab; if( pTab ){ pTab->nRef++; } pNewItem->pSelect = sqlite3SelectDup(pOldItem->pSelect); pNewItem->pOn = sqlite3ExprDup(pOldItem->pOn); pNewItem->pUsing = sqlite3IdListDup(pOldItem->pUsing); pNewItem->colUsed = pOldItem->colUsed; } return pNew; |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** 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 SELECT statements in SQLite. ** | | | 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 SELECT statements in SQLite. ** ** $Id: select.c,v 1.250 2005/06/06 21:19:57 drh Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. |
︙ | ︙ | |||
868 869 870 871 872 873 874 875 876 877 878 879 880 881 | if( sqlite3SelectResolve(pParse, pSelect, 0) ){ return 0; } pTab = sqliteMalloc( sizeof(Table) ); if( pTab==0 ){ return 0; } pTab->zName = zTabName ? sqliteStrDup(zTabName) : 0; pEList = pSelect->pEList; pTab->nCol = pEList->nExpr; assert( pTab->nCol>0 ); pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol ); for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){ Expr *p, *pR; | > | 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 | if( sqlite3SelectResolve(pParse, pSelect, 0) ){ return 0; } pTab = sqliteMalloc( sizeof(Table) ); if( pTab==0 ){ return 0; } pTab->nRef = 1; pTab->zName = zTabName ? sqliteStrDup(zTabName) : 0; pEList = pSelect->pEList; pTab->nCol = pEList->nExpr; assert( pTab->nCol>0 ); pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol ); for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){ Expr *p, *pR; |
︙ | ︙ | |||
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 | #ifndef SQLITE_OMIT_SUBQUERY /* A sub-query in the FROM clause of a SELECT */ assert( pFrom->pSelect!=0 ); if( pFrom->zAlias==0 ){ pFrom->zAlias = sqlite3MPrintf("sqlite_subquery_%p_", (void*)pFrom->pSelect); } pFrom->pTab = pTab = sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect); if( pTab==0 ){ return 1; } /* The isTransient flag indicates that the Table structure has been ** dynamically allocated and may be freed at any time. In other words, ** pTab is not pointing to a persistent table structure that defines ** part of the schema. */ pTab->isTransient = 1; #endif }else{ /* An ordinary table or view name in the FROM clause */ pFrom->pTab = pTab = sqlite3LocateTable(pParse,pFrom->zName,pFrom->zDatabase); if( pTab==0 ){ return 1; } #ifndef SQLITE_OMIT_VIEW if( pTab->pSelect ){ /* We reach here if the named table is a really a view */ if( sqlite3ViewGetColumnNames(pParse, pTab) ){ return 1; } /* If pFrom->pSelect!=0 it means we are dealing with a | > > > | 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 | #ifndef SQLITE_OMIT_SUBQUERY /* A sub-query in the FROM clause of a SELECT */ assert( pFrom->pSelect!=0 ); if( pFrom->zAlias==0 ){ pFrom->zAlias = sqlite3MPrintf("sqlite_subquery_%p_", (void*)pFrom->pSelect); } assert( pFrom->pTab==0 ); pFrom->pTab = pTab = sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect); if( pTab==0 ){ return 1; } /* The isTransient flag indicates that the Table structure has been ** dynamically allocated and may be freed at any time. In other words, ** pTab is not pointing to a persistent table structure that defines ** part of the schema. */ pTab->isTransient = 1; #endif }else{ /* An ordinary table or view name in the FROM clause */ assert( pFrom->pTab==0 ); pFrom->pTab = pTab = sqlite3LocateTable(pParse,pFrom->zName,pFrom->zDatabase); if( pTab==0 ){ return 1; } pTab->nRef++; #ifndef SQLITE_OMIT_VIEW if( pTab->pSelect ){ /* We reach here if the named table is a really a view */ if( sqlite3ViewGetColumnNames(pParse, pTab) ){ return 1; } /* If pFrom->pSelect!=0 it means we are dealing with a |
︙ | ︙ | |||
1160 1161 1162 1163 1164 1165 1166 | } sqlite3ExprListDelete(pEList); p->pEList = pNew; } return rc; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 | } sqlite3ExprListDelete(pEList); p->pEList = pNew; } return rc; } #ifndef SQLITE_OMIT_COMPOUND_SELECT /* ** This routine associates entries in an ORDER BY expression list with ** columns in a result. For each ORDER BY expression, the opcode of ** the top-level node is changed to TK_COLUMN and the iColumn value of ** the top-level node is filled in with column number and the iTable ** value of the top-level node is filled with iTable parameter. |
︙ | ︙ | |||
2044 2045 2046 2047 2048 2049 2050 | ** those references with expressions that resolve to the subquery FROM ** elements we are now copying in. */ iParent = pSubitem->iCursor; { int nSubSrc = pSubSrc->nSrc; int jointype = pSubitem->jointype; | < < | < | 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 | ** those references with expressions that resolve to the subquery FROM ** elements we are now copying in. */ iParent = pSubitem->iCursor; { int nSubSrc = pSubSrc->nSrc; int jointype = pSubitem->jointype; sqlite3DeleteTable(0, pSubitem->pTab); sqliteFree(pSubitem->zDatabase); sqliteFree(pSubitem->zName); sqliteFree(pSubitem->zAlias); if( nSubSrc>1 ){ int extra = nSubSrc - 1; for(i=1; i<nSubSrc; i++){ pSrc = sqlite3SrcListAppend(pSrc, 0, 0); |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** 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. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** 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.386 2005/06/06 21:19:57 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** These #defines should enable >2GB file support on Posix if the ** underlying operating system supports it. If the OS lacks |
︙ | ︙ | |||
603 604 605 606 607 608 609 610 611 612 613 614 615 616 | Select *pSelect; /* NULL for tables. Points to definition if a view. */ u8 readOnly; /* True if this table should not be written by the user */ u8 iDb; /* Index into sqlite.aDb[] of the backend for this table */ u8 isTransient; /* True if automatically deleted when VDBE finishes */ u8 hasPrimKey; /* True if there exists a primary key */ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ u8 autoInc; /* True if the integer primary key is autoincrement */ Trigger *pTrigger; /* List of SQL triggers on this table */ FKey *pFKey; /* Linked list of all foreign keys in this table */ char *zColAff; /* String defining the affinity of each column */ #ifndef SQLITE_OMIT_ALTERTABLE int addColOffset; /* Offset in CREATE TABLE statement to add a new column */ #endif }; | > | 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 | Select *pSelect; /* NULL for tables. Points to definition if a view. */ u8 readOnly; /* True if this table should not be written by the user */ u8 iDb; /* Index into sqlite.aDb[] of the backend for this table */ u8 isTransient; /* True if automatically deleted when VDBE finishes */ u8 hasPrimKey; /* True if there exists a primary key */ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ u8 autoInc; /* True if the integer primary key is autoincrement */ int nRef; /* Number of pointers to this Table */ Trigger *pTrigger; /* List of SQL triggers on this table */ FKey *pFKey; /* Linked list of all foreign keys in this table */ char *zColAff; /* String defining the affinity of each column */ #ifndef SQLITE_OMIT_ALTERTABLE int addColOffset; /* Offset in CREATE TABLE statement to add a new column */ #endif }; |
︙ | ︙ |
Changes to test/misc5.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for miscellanous features that were # left out of other test files. # | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for miscellanous features that were # left out of other test files. # # $Id: misc5.test,v 1.3 2005/06/06 21:19:58 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Build records using the MakeRecord opcode such that the size of the # header is at the transition point in the size of a varint. # |
︙ | ︙ | |||
432 433 434 435 436 437 438 | 2305843009213693951\ 2305843009213693952\ 2305843009213693953\ 4611686018427387903\ 4611686018427387904\ 4611686018427387905" | > > | > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > | 432 433 434 435 436 437 438 439 440 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 471 472 473 474 475 476 | 2305843009213693951\ 2305843009213693952\ 2305843009213693953\ 4611686018427387903\ 4611686018427387904\ 4611686018427387905" # Ticket #1210. Do proper reference counting of Table structures # so that deeply nested SELECT statements can be flattened correctly. # do_test misc5-3.1 { execsql { CREATE TABLE songs(songid, artist, timesplayed); INSERT INTO songs VALUES(1,'one',1); INSERT INTO songs VALUES(2,'one',2); INSERT INTO songs VALUES(3,'two',3); INSERT INTO songs VALUES(4,'three',5); INSERT INTO songs VALUES(5,'one',7); INSERT INTO songs VALUES(6,'two',11); SELECT DISTINCT artist FROM ( SELECT DISTINCT artist FROM songs WHERE songid IN ( SELECT songid FROM songs WHERE LOWER(artist) = ( SELECT DISTINCT LOWER(artist) FROM ( SELECT DISTINCT artist,sum(timesplayed) AS total FROM songs GROUP BY LOWER(artist) ORDER BY total DESC LIMIT 10 ) WHERE artist <> '' ) ) ) ORDER BY LOWER(artist) ASC; } } {two} finish_test |