Version History
-
1.0.84.0 - March XX, 2013 (release scheduled)
+
1.0.84.0 - January 9, 2013
- - Updated to SQLite 3.7.16.
+ - Updated to SQLite 3.7.15.2.
+ - Explicitly dispose of all SQLiteCommand objects managed by the DbDataAdapter class. Fix for [6434e23a0f].
- Add Cancel method to the SQLiteConnection class to interrupt a long running query.
- Improve thread safety of the SQLiteLog.LogMessage method.
1.0.83.0 - December 29, 2012
Index: Doc/SQLite.NET.chm
==================================================================
--- Doc/SQLite.NET.chm
+++ Doc/SQLite.NET.chm
cannot compute difference between binary files
Index: Externals/Eagle/lib/Eagle1.0/init.eagle
==================================================================
--- Externals/Eagle/lib/Eagle1.0/init.eagle
+++ Externals/Eagle/lib/Eagle1.0/init.eagle
@@ -141,11 +141,11 @@
proc lappendArgs { args } {
#
# NOTE: This should work properly in both Tcl and Eagle.
#
- eval lappend result $args
+ set result [list]; eval lappend result $args
}
proc getDictionaryValue { dictionary name {default ""} {wrap ""} } {
#
# NOTE: Locate the named value we are interested in. The dictionary must
@@ -1045,47 +1045,28 @@
#
# NOTE: Next, figure out what type of download is being
# requested.
#
switch -exact -nocase -- $type {
- source {
- #
- # NOTE: Source code download. This may be a RAR or an EXE
- # file. Append the appropriate file name and then
- # join all the URI components to form the final URI.
- #
- set fileName [appendArgs EagleSource $patchLevel $extension]
- lappend components $fileName
-
- set result [list [eval uri join $components] \
- [file join $directory $fileName]]
- }
- setup {
- #
- # NOTE: Windows setup download. Always append an ".exe"
- # extension because we never distribute the setup as
- # a RAR file. Append the appropriate file name and
- # then join all the URI components to form the final
- # URI.
- #
- set fileName [appendArgs EagleSetup $patchLevel .exe]
- lappend components $fileName
-
- set result [list [eval uri join $components] \
- [file join $directory $fileName]]
- }
- binary {
- #
- # NOTE: Binary file download. This may be a RAR or an EXE
- # file. Append the appropriate file name and then
- # join all the URI components to form the final URI.
- #
- set fileName [appendArgs EagleBinary $patchLevel $extension]
- lappend components $fileName
-
- set result [list [eval uri join $components] \
- [file join $directory $fileName]]
+ source -
+ setup -
+ binary {
+ #
+ # NOTE: Source code, setup, or binary download. This may be
+ # a RAR or an EXE file. Append the appropriate file
+ # name and then join all the URI components to form the
+ # final URI.
+ #
+ set fileName [appendArgs \
+ [info engine] [string totitle $type] $patchLevel \
+ [expr {[string tolower $type] eq "setup" ? ".exe" : \
+ $extension}]]
+
+ lappend components $fileName
+
+ set result [list [eval uri join $components] [file join \
+ $directory $fileName]]
}
}
}
}
}
@@ -1554,25 +1535,48 @@
#
# NOTE: This should work properly in both Tcl and Eagle.
#
catch {puts stderr $string}
}
+
+ proc makeVariableFast { name fast } {
+ #
+ # NOTE: This should work properly in Eagle only.
+ #
+ catch {
+ uplevel 1 [list object invoke -flags +NonPublic \
+ Interpreter.GetActive MakeVariableFast $name $fast]
+ }
+ }
proc findDirectories { pattern } {
+ #
+ # NOTE: Block non-Windows platforms since this is Windows specific.
+ #
+ if {$::tcl_platform(platform) ne "windows"} then {
+ error "not supported on this operating system"
+ }
+
#
# NOTE: This should work properly in Eagle only.
#
- set result [list]
+ set dir ""; set result [list]
+
+ #
+ # HACK: Optimize the variable access in this procedure to be
+ # as fast as possible.
+ #
+ makeVariableFast dir true; makeVariableFast result true
foreach dir [split [exec -unicode $::env(ComSpec) /u /c dir \
/ad /b [appendArgs \" [file nativename $pattern] \"]] \n] {
set dir [string trim $dir]
if {[string length $dir] > 0} then {
set dir [getDirResultPath $pattern $dir]
- if {[lsearch -exact -nocase $result $dir] == -1} then {
+ if {[lsearch -variable -exact -nocase result $dir] == -1} then {
lappend result $dir
}
}
}
@@ -1581,33 +1585,46 @@
set dir [string trim $dir]
if {[string length $dir] > 0} then {
set dir [getDirResultPath $pattern $dir]
- if {[lsearch -exact -nocase $result $dir] == -1} then {
+ if {[lsearch -variable -exact -nocase result $dir] == -1} then {
lappend result $dir
}
}
}
return $result
}
proc findFiles { pattern } {
+ #
+ # NOTE: Block non-Windows platforms since this is Windows specific.
+ #
+ if {$::tcl_platform(platform) ne "windows"} then {
+ error "not supported on this operating system"
+ }
+
#
# NOTE: This should work properly in Eagle only.
#
- set result [list]
+ set fileName ""; set result [list]
+
+ #
+ # HACK: Optimize the variable access in this procedure to be
+ # as fast as possible.
+ #
+ makeVariableFast fileName true; makeVariableFast result true
foreach fileName [split [exec -unicode $::env(ComSpec) /u /c dir \
/a-d /b [appendArgs \" [file nativename $pattern] \"]] \n] {
set fileName [string trim $fileName]
if {[string length $fileName] > 0} then {
set fileName [getDirResultPath $pattern $fileName]
- if {[lsearch -exact -nocase $result $fileName] == -1} then {
+ if {[lsearch -variable -exact -nocase result $fileName] == -1} then {
lappend result $fileName
}
}
}
@@ -1616,33 +1633,46 @@
set fileName [string trim $fileName]
if {[string length $fileName] > 0} then {
set fileName [getDirResultPath $pattern $fileName]
- if {[lsearch -exact -nocase $result $fileName] == -1} then {
+ if {[lsearch -variable -exact -nocase result $fileName] == -1} then {
lappend result $fileName
}
}
}
return $result
}
proc findFilesRecursive { pattern } {
+ #
+ # NOTE: Block non-Windows platforms since this is Windows specific.
+ #
+ if {$::tcl_platform(platform) ne "windows"} then {
+ error "not supported on this operating system"
+ }
+
#
# NOTE: This should work properly in Eagle only.
#
- set result [list]
+ set fileName ""; set result [list]
+
+ #
+ # HACK: Optimize the variable access in this procedure to be
+ # as fast as possible.
+ #
+ makeVariableFast fileName true; makeVariableFast result true
foreach fileName [split [exec -unicode $::env(ComSpec) /u /c dir \
/a-d /s /b [appendArgs \" [file nativename $pattern] \"]] \n] {
set fileName [string trim $fileName]
if {[string length $fileName] > 0} then {
set fileName [getDirResultPath $pattern $fileName]
- if {[lsearch -exact -nocase $result $fileName] == -1} then {
+ if {[lsearch -variable -exact -nocase result $fileName] == -1} then {
lappend result $fileName
}
}
}
@@ -1651,11 +1681,11 @@
set fileName [string trim $fileName]
if {[string length $fileName] > 0} then {
set fileName [getDirResultPath $pattern $fileName]
- if {[lsearch -exact -nocase $result $fileName] == -1} then {
+ if {[lsearch -variable -exact -nocase result $fileName] == -1} then {
lappend result $fileName
}
}
}
@@ -1709,10 +1739,17 @@
return $result
}
proc findFilesRecursive { pattern } {
+ #
+ # NOTE: Block non-Windows platforms since this is Windows specific.
+ #
+ if {$::tcl_platform(platform) ne "windows"} then {
+ error "not supported on this operating system"
+ }
+
#
# NOTE: This should work properly in Tcl only.
#
set result [list]
@@ -1796,14 +1833,19 @@
#
# NOTE: Exports the necessary commands from this package and import them
# into the global namespace.
#
exportAndImportPackageCommands [namespace current] [list \
- exportAndImportPackageCommands isEagle isMono getEnvironmentVariable \
- getPluginPath getDictionaryValue getColumnValue getRowColumnValue \
- appendArgs haveGaruda lappendArgs readFile writeFile filter map \
- reduce getPlatformInfo execShell combineFlags tqputs tqlog] false false
+ isEagle haveGaruda isMono getEnvironmentVariable combineFlags \
+ getCompileInfo getPlatformInfo getPluginPath appendArgs lappendArgs \
+ getDictionaryValue getColumnValue getRowColumnValue tqputs tqlog \
+ readFile readSharedFile writeFile appendFile appendLogFile \
+ appendSharedFile appendSharedLogFile readAsciiFile writeAsciiFile \
+ readUnicodeFile writeUnicodeFile getDirResultPath addToPath \
+ removeFromPath execShell ldifference filter map reduce \
+ getLengthModifier debug findDirectories findFiles findFilesRecursive \
+ exportAndImportPackageCommands] false false
###########################################################################
############################## END Tcl ONLY ###############################
###########################################################################
}
Index: Externals/Eagle/lib/Eagle1.0/test.eagle
==================================================================
--- Externals/Eagle/lib/Eagle1.0/test.eagle
+++ Externals/Eagle/lib/Eagle1.0/test.eagle
@@ -1318,10 +1318,16 @@
# output diagnostics as necessary if they have.
#
reportTestStatistics $channel $fileName leaks leaked
}
} else {
+ #
+ # NOTE: This entire file has been skipped. Record that fact in the
+ # test suite log file.
+ #
+ tputs $channel [appendArgs "==== \"" $fileName "\" NON_TEST_FILE\n"]
+
#
# NOTE: This file does not actually count towards the total (i.e.
# it contains no actual tests).
#
incr total -1
@@ -1348,12 +1354,12 @@
if {$stop} then {
break
}
} else {
#
- # NOTE: This entire test file has been skipped. Record that fact in
- # the test suite log file.
+ # NOTE: This entire file has been skipped. Record that fact in the
+ # test suite log file.
#
tputs $channel [appendArgs "==== \"" $fileName "\" SKIPPED\n"]
#
# NOTE: This file does not actually count towards the total (i.e.
Index: SQLite.Interop/props/sqlite3.props
==================================================================
--- SQLite.Interop/props/sqlite3.props
+++ SQLite.Interop/props/sqlite3.props
@@ -7,12 +7,12 @@
* Released to the public domain, use at your own risk!
*
-->
- 3.7.16
- 3,7,16
+ 3.7.15.2
+ 3,7,15,2
_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;SQLITE_THREADSAFE=1;SQLITE_USE_URI=1;SQLITE_ENABLE_COLUMN_METADATA=1;SQLITE_ENABLE_STAT3=1;SQLITE_ENABLE_FTS3=1;SQLITE_ENABLE_LOAD_EXTENSION=1;SQLITE_ENABLE_RTREE=1;SQLITE_SOUNDEX=1
SQLITE_HAS_CODEC=1
SQLITE_OMIT_WAL=1
SQLITE_DEBUG=1;SQLITE_MEMDEBUG=1;SQLITE_ENABLE_EXPENSIVE_ASSERT=1
SQLITE_WIN32_MALLOC=1
Index: SQLite.Interop/props/sqlite3.vsprops
==================================================================
--- SQLite.Interop/props/sqlite3.vsprops
+++ SQLite.Interop/props/sqlite3.vsprops
@@ -12,16 +12,16 @@
Version="8.00"
Name="sqlite3"
>
pPage1->aData[32]),
@@ -56882,16 +56869,11 @@
/*
** Parameter zSrcData points to a buffer containing the data for
** page iSrcPg from the source database. Copy this data into the
** destination database.
*/
-static int backupOnePage(
- sqlite3_backup *p, /* Backup handle */
- Pgno iSrcPg, /* Source database page to backup */
- const u8 *zSrcData, /* Source database page data */
- int bUpdate /* True for an update, false otherwise */
-){
+static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
Pager * const pDestPager = sqlite3BtreePager(p->pDest);
const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc);
int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
const int nCopy = MIN(nSrcPgsz, nDestPgsz);
const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
@@ -56960,13 +56942,10 @@
** cached parse of the page). MemPage.isInit is marked
** "MUST BE FIRST" for this purpose.
*/
memcpy(zOut, zIn, nCopy);
((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0;
- if( iOff==0 && bUpdate==0 ){
- sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc));
- }
}
sqlite3PagerUnref(pDestPg);
}
return rc;
@@ -57069,11 +57048,11 @@
const Pgno iSrcPg = p->iNext; /* Source page number */
if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
DbPage *pSrcPg; /* Source page object */
rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
if( rc==SQLITE_OK ){
- rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
+ rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg));
sqlite3PagerUnref(pSrcPg);
}
}
p->iNext++;
}
@@ -57317,11 +57296,11 @@
** the new data into the backup.
*/
int rc;
assert( p->pDestDb );
sqlite3_mutex_enter(p->pDestDb->mutex);
- rc = backupOnePage(p, iPage, aData, 1);
+ rc = backupOnePage(p, iPage, aData);
sqlite3_mutex_leave(p->pDestDb->mutex);
assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED );
if( rc!=SQLITE_OK ){
p->rc = rc;
}
@@ -71911,18 +71890,10 @@
p->pReal = pReal;
if( p->iSize>0 ){
assert(p->iSize<=p->nBuf);
rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0);
}
- if( rc!=SQLITE_OK ){
- /* If an error occurred while writing to the file, close it before
- ** returning. This way, SQLite uses the in-memory journal data to
- ** roll back changes made to the internal page-cache before this
- ** function was called. */
- sqlite3OsClose(pReal);
- p->pReal = 0;
- }
}
}
return rc;
}
@@ -72665,39 +72636,10 @@
}
}
return 0;
}
-/*
-** Subqueries stores the original database, table and column names for their
-** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN".
-** Check to see if the zSpan given to this routine matches the zDb, zTab,
-** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will
-** match anything.
-*/
-SQLITE_PRIVATE int sqlite3MatchSpanName(
- const char *zSpan,
- const char *zCol,
- const char *zTab,
- const char *zDb
-){
- int n;
- for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
- if( zDb && sqlite3StrNICmp(zSpan, zDb, n)!=0 ){
- return 0;
- }
- zSpan += n+1;
- for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
- if( zTab && sqlite3StrNICmp(zSpan, zTab, n)!=0 ){
- return 0;
- }
- zSpan += n+1;
- if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){
- return 0;
- }
- return 1;
-}
/*
** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
** that name in the set of source tables in pSrcList and make the pExpr
** expression node refer back to that source column. The following changes
@@ -72750,62 +72692,43 @@
/* Initialize the node to no-match */
pExpr->iTable = -1;
pExpr->pTab = 0;
ExprSetIrreducible(pExpr);
- /* Translate the schema name in zDb into a pointer to the corresponding
- ** schema. If not found, pSchema will remain NULL and nothing will match
- ** resulting in an appropriate error message toward the end of this routine
- */
- if( zDb ){
- for(i=0; inDb; i++){
- assert( db->aDb[i].zName );
- if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){
- pSchema = db->aDb[i].pSchema;
- break;
- }
- }
- }
-
/* Start at the inner-most context and move outward until a match is found */
while( pNC && cnt==0 ){
ExprList *pEList;
SrcList *pSrcList = pNC->pSrcList;
if( pSrcList ){
for(i=0, pItem=pSrcList->a; inSrc; i++, pItem++){
Table *pTab;
+ int iDb;
Column *pCol;
pTab = pItem->pTab;
assert( pTab!=0 && pTab->zName!=0 );
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( pTab->nCol>0 );
- if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){
- ExprList *pEList = pItem->pSelect->pEList;
- int hit = 0;
- for(j=0; jnExpr; j++){
- if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){
- cnt++;
- cntTab = 2;
- pMatch = pItem;
- pExpr->iColumn = j;
- hit = 1;
- }
- }
- if( hit || zTab==0 ) continue;
- }
- if( zDb && pTab->pSchema!=pSchema ){
- continue;
- }
if( zTab ){
- const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
- assert( zTabName!=0 );
- if( sqlite3StrICmp(zTabName, zTab)!=0 ){
- continue;
+ if( pItem->zAlias ){
+ char *zTabName = pItem->zAlias;
+ if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
+ }else{
+ char *zTabName = pTab->zName;
+ if( NEVER(zTabName==0) || sqlite3StrICmp(zTabName, zTab)!=0 ){
+ continue;
+ }
+ if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){
+ continue;
+ }
}
}
if( 0==(cntTab++) ){
+ pExpr->iTable = pItem->iCursor;
+ pExpr->pTab = pTab;
+ pSchema = pTab->pSchema;
pMatch = pItem;
}
for(j=0, pCol=pTab->aCol; jnCol; j++, pCol++){
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
/* If there has been exactly one prior match and this match
@@ -72815,23 +72738,21 @@
if( cnt==1 ){
if( pItem->jointype & JT_NATURAL ) continue;
if( nameInUsingClause(pItem->pUsing, zCol) ) continue;
}
cnt++;
+ pExpr->iTable = pItem->iCursor;
+ pExpr->pTab = pTab;
pMatch = pItem;
+ pSchema = pTab->pSchema;
/* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
break;
}
}
}
- if( pMatch ){
- pExpr->iTable = pMatch->iCursor;
- pExpr->pTab = pMatch->pTab;
- pSchema = pExpr->pTab->pSchema;
- }
- } /* if( pSrcList ) */
+ }
#ifndef SQLITE_OMIT_TRIGGER
/* If we have not already resolved the name, then maybe
** it is a new.* or old.* trigger argument reference
*/
@@ -73597,10 +73518,27 @@
sNC.pParse = pParse;
if( sqlite3ResolveExprNames(&sNC, p->pLimit) ||
sqlite3ResolveExprNames(&sNC, p->pOffset) ){
return WRC_Abort;
}
+
+ /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
+ ** resolve the result-set expression list.
+ */
+ sNC.ncFlags = NC_AllowAgg;
+ sNC.pSrcList = p->pSrc;
+ sNC.pNext = pOuterNC;
+
+ /* Resolve names in the result set. */
+ pEList = p->pEList;
+ assert( pEList!=0 );
+ for(i=0; inExpr; i++){
+ Expr *pX = pEList->a[i].pExpr;
+ if( sqlite3ResolveExprNames(&sNC, pX) ){
+ return WRC_Abort;
+ }
+ }
/* Recursively resolve names in all subqueries
*/
for(i=0; ipSrc->nSrc; i++){
struct SrcList_item *pItem = &p->pSrc->a[i];
@@ -73625,27 +73563,10 @@
assert( pItem->isCorrelated==0 && nRef<=0 );
pItem->isCorrelated = (nRef!=0);
}
}
- /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
- ** resolve the result-set expression list.
- */
- sNC.ncFlags = NC_AllowAgg;
- sNC.pSrcList = p->pSrc;
- sNC.pNext = pOuterNC;
-
- /* Resolve names in the result set. */
- pEList = p->pEList;
- assert( pEList!=0 );
- for(i=0; inExpr; i++){
- Expr *pX = pEList->a[i].pExpr;
- if( sqlite3ResolveExprNames(&sNC, pX) ){
- return WRC_Abort;
- }
- }
-
/* If there are no aggregate functions in the result-set, and no GROUP BY
** expression, do not allow aggregates in any of the other expressions.
*/
assert( (p->selFlags & SF_Aggregate)==0 );
pGroupBy = p->pGroupBy;
@@ -77125,16 +77046,10 @@
for(i=0; inExpr; i++){
sqlite3ExplainPrintf(pOut, "item[%d] = ", i);
sqlite3ExplainPush(pOut);
sqlite3ExplainExpr(pOut, pList->a[i].pExpr);
sqlite3ExplainPop(pOut);
- if( pList->a[i].zName ){
- sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName);
- }
- if( pList->a[i].bSpanIsTab ){
- sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan);
- }
if( inExpr-1 ){
sqlite3ExplainNL(pOut);
}
}
sqlite3ExplainPop(pOut);
@@ -87608,11 +87523,11 @@
/*
** A foreign key constraint requires that the key columns in the parent
** table are collectively subject to a UNIQUE or PRIMARY KEY constraint.
** Given that pParent is the parent table for foreign key constraint pFKey,
-** search the schema for a unique index on the parent key columns.
+** search the schema a unique index on the parent key columns.
**
** If successful, zero is returned. If the parent key is an INTEGER PRIMARY
** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx
** is set to point to the unique index.
**
@@ -87644,11 +87559,11 @@
**
** then non-zero is returned, and a "foreign key mismatch" error loaded
** into pParse. If an OOM error occurs, non-zero is returned and the
** pParse->db->mallocFailed flag is set.
*/
-SQLITE_PRIVATE int sqlite3FkLocateIndex(
+static int locateFkeyIndex(
Parse *pParse, /* Parse context to store any error in */
Table *pParent, /* Parent table of FK constraint pFKey */
FKey *pFKey, /* Foreign key to find index for */
Index **ppIdx, /* OUT: Unique index on parent table */
int **paiCol /* OUT: Map of index columns in pFKey */
@@ -87741,13 +87656,11 @@
}
}
if( !pIdx ){
if( !pParse->disableTriggers ){
- sqlite3ErrorMsg(pParse,
- "foreign key mismatch - \"%w\" referencing \"%w\"",
- pFKey->pFrom->zName, pFKey->zTo);
+ sqlite3ErrorMsg(pParse, "foreign key mismatch");
}
sqlite3DbFree(pParse->db, aiCol);
return 1;
}
@@ -88204,11 +88117,11 @@
if( pParse->disableTriggers ){
pTo = sqlite3FindTable(db, pFKey->zTo, zDb);
}else{
pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
}
- if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
+ if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) );
if( !isIgnoreErrors || db->mallocFailed ) return;
if( pTo==0 ){
/* If isIgnoreErrors is true, then a table is being dropped. In this
** case SQLite runs a "DELETE FROM xxx" on the table being dropped
@@ -88284,11 +88197,11 @@
/* Inserting a single row into a parent table cannot cause an immediate
** foreign key violation. So do nothing in this case. */
continue;
}
- if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
+ if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
if( !isIgnoreErrors || db->mallocFailed ) return;
continue;
}
assert( aiCol || pFKey->nCol==1 );
@@ -88339,11 +88252,11 @@
for(p=pTab->pFKey; p; p=p->pNextFrom){
for(i=0; inCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom);
}
for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
Index *pIdx = 0;
- sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
+ locateFkeyIndex(pParse, pTab, p, &pIdx, 0);
if( pIdx ){
for(i=0; inColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
}
}
}
@@ -88465,11 +88378,11 @@
ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */
Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */
int i; /* Iterator variable */
Expr *pWhen = 0; /* WHEN clause for the trigger */
- if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
+ if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
assert( aiCol || pFKey->nCol==1 );
for(i=0; inCol; i++){
Token tOld = { "old", 3 }; /* Literal "old" token */
Token tNew = { "new", 3 }; /* Literal "new" token */
@@ -92805,15 +92718,13 @@
if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){
Table *pTab;
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
pTab = sqlite3FindTable(db, zRight, zDb);
if( pTab ){
- int i, k;
+ int i;
int nHidden = 0;
Column *pCol;
- Index *pPk;
- for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){}
sqlite3VdbeSetNumCols(v, 6);
pParse->nMem = 6;
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC);
@@ -92834,18 +92745,12 @@
if( pCol->zDflt ){
sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, 5);
}
- if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
- k = 0;
- }else if( pPk==0 ){
- k = 1;
- }else{
- for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){}
- }
- sqlite3VdbeAddOp2(v, OP_Integer, k, 6);
+ sqlite3VdbeAddOp2(v, OP_Integer,
+ (pCol->colFlags&COLFLAG_PRIMKEY)!=0, 6);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
}
}
}else
@@ -92976,124 +92881,10 @@
++i;
pFK = pFK->pNextFrom;
}
}
}
- }else
-#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
-
-#ifndef SQLITE_OMIT_FOREIGN_KEY
- if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 ){
- FKey *pFK; /* A foreign key constraint */
- Table *pTab; /* Child table contain "REFERENCES" keyword */
- Table *pParent; /* Parent table that child points to */
- Index *pIdx; /* Index in the parent table */
- int i; /* Loop counter: Foreign key number for pTab */
- int j; /* Loop counter: Field of the foreign key */
- HashElem *k; /* Loop counter: Next table in schema */
- int x; /* result variable */
- int regResult; /* 3 registers to hold a result row */
- int regKey; /* Register to hold key for checking the FK */
- int regRow; /* Registers to hold a row from pTab */
- int addrTop; /* Top of a loop checking foreign keys */
- int addrOk; /* Jump here if the key is OK */
- int *aiCols; /* child to parent column mapping */
-
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
- regResult = pParse->nMem+1;
- pParse->nMem += 4;
- regKey = ++pParse->nMem;
- regRow = ++pParse->nMem;
- v = sqlite3GetVdbe(pParse);
- sqlite3VdbeSetNumCols(v, 4);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "parent", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "fkid", SQLITE_STATIC);
- sqlite3CodeVerifySchema(pParse, iDb);
- k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
- while( k ){
- if( zRight ){
- pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
- k = 0;
- }else{
- pTab = (Table*)sqliteHashData(k);
- k = sqliteHashNext(k);
- }
- if( pTab==0 || pTab->pFKey==0 ) continue;
- sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
- if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
- sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
- sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName,
- P4_TRANSIENT);
- for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
- pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
- if( pParent==0 ) break;
- pIdx = 0;
- sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
- x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
- if( x==0 ){
- if( pIdx==0 ){
- sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead);
- }else{
- KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
- sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb);
- sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
- }
- }else{
- k = 0;
- break;
- }
- }
- if( pFK ) break;
- if( pParse->nTabnTab = i;
- addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0);
- for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
- pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
- assert( pParent!=0 );
- pIdx = 0;
- aiCols = 0;
- x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
- assert( x==0 );
- addrOk = sqlite3VdbeMakeLabel(v);
- if( pIdx==0 ){
- int iKey = pFK->aCol[0].iFrom;
- assert( iKey>=0 && iKeynCol );
- if( iKey!=pTab->iPKey ){
- sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
- sqlite3ColumnDefault(v, pTab, iKey, regRow);
- sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk);
- sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow,
- sqlite3VdbeCurrentAddr(v)+3);
- }else{
- sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow);
- }
- sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow);
- sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk);
- sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
- }else{
- for(j=0; jnCol; j++){
- sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
- aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j);
- sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk);
- }
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
- sqlite3VdbeChangeP4(v, -1,
- sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
- sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
- }
- sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
- sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0,
- pFK->zTo, P4_TRANSIENT);
- sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3);
- sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4);
- sqlite3VdbeResolveLabel(v, addrOk);
- sqlite3DbFree(db, aiCols);
- }
- sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1);
- sqlite3VdbeJumpHere(v, addrTop);
- }
}else
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
#ifndef NDEBUG
if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
@@ -94549,11 +94340,11 @@
SrcList *pSrc, /* the FROM clause -- which tables to scan */
Expr *pWhere, /* the WHERE clause */
ExprList *pGroupBy, /* the GROUP BY clause */
Expr *pHaving, /* the HAVING clause */
ExprList *pOrderBy, /* the ORDER BY clause */
- u16 selFlags, /* Flag parameters, such as SF_Distinct */
+ int isDistinct, /* true if the DISTINCT keyword is present */
Expr *pLimit, /* LIMIT value. NULL means not used */
Expr *pOffset /* OFFSET value. NULL means no offset */
){
Select *pNew;
Select standin;
@@ -94573,11 +94364,11 @@
pNew->pSrc = pSrc;
pNew->pWhere = pWhere;
pNew->pGroupBy = pGroupBy;
pNew->pHaving = pHaving;
pNew->pOrderBy = pOrderBy;
- pNew->selFlags = selFlags;
+ pNew->selFlags = isDistinct ? SF_Distinct : 0;
pNew->op = TK_SELECT;
pNew->pLimit = pLimit;
pNew->pOffset = pOffset;
assert( pOffset==0 || pLimit!=0 );
pNew->addrOpenEphm[0] = -1;
@@ -95830,10 +95621,12 @@
for(i=0, pCol=aCol; ia[i].pExpr);
+ assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue)
+ || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 );
if( (zName = pEList->a[i].zName)!=0 ){
/* If the column contains an "AS " phrase, use as the name */
zName = sqlite3DbStrDup(db, zName);
}else{
Expr *pColExpr = p; /* The expression that is the result column name */
@@ -95867,13 +95660,10 @@
*/
nName = sqlite3Strlen30(zName);
for(j=cnt=0; j1 && sqlite3Isdigit(zName[k]); k--){}
- if( zName[k]==':' ) nName = k;
zName[nName] = 0;
zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
sqlite3DbFree(db, zName);
zName = zNewName;
j = -1;
@@ -97655,47 +97445,38 @@
return 1;
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
/*
-** Based on the contents of the AggInfo structure indicated by the first
-** argument, this function checks if the following are true:
-**
-** * the query contains just a single aggregate function,
-** * the aggregate function is either min() or max(), and
-** * the argument to the aggregate function is a column value.
-**
-** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX
-** is returned as appropriate. Also, *ppMinMax is set to point to the
-** list of arguments passed to the aggregate before returning.
-**
-** Or, if the conditions above are not met, *ppMinMax is set to 0 and
-** WHERE_ORDERBY_NORMAL is returned.
-*/
-static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){
- int eRet = WHERE_ORDERBY_NORMAL; /* Return value */
-
- *ppMinMax = 0;
- if( pAggInfo->nFunc==1 ){
- Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */
- ExprList *pEList = pExpr->x.pList; /* Arguments to agg function */
-
- assert( pExpr->op==TK_AGG_FUNCTION );
- if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){
- const char *zFunc = pExpr->u.zToken;
- if( sqlite3StrICmp(zFunc, "min")==0 ){
- eRet = WHERE_ORDERBY_MIN;
- *ppMinMax = pEList;
- }else if( sqlite3StrICmp(zFunc, "max")==0 ){
- eRet = WHERE_ORDERBY_MAX;
- *ppMinMax = pEList;
- }
- }
- }
-
- assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 );
- return eRet;
+** Analyze the SELECT statement passed as an argument to see if it
+** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if
+** it is, or 0 otherwise. At present, a query is considered to be
+** a min()/max() query if:
+**
+** 1. There is a single object in the FROM clause.
+**
+** 2. There is a single expression in the result set, and it is
+** either min(x) or max(x), where x is a column reference.
+*/
+static u8 minMaxQuery(Select *p){
+ Expr *pExpr;
+ ExprList *pEList = p->pEList;
+
+ if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL;
+ pExpr = pEList->a[0].pExpr;
+ if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
+ if( NEVER(ExprHasProperty(pExpr, EP_xIsSelect)) ) return 0;
+ pEList = pExpr->x.pList;
+ if( pEList==0 || pEList->nExpr!=1 ) return 0;
+ if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL;
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ if( sqlite3StrICmp(pExpr->u.zToken,"min")==0 ){
+ return WHERE_ORDERBY_MIN;
+ }else if( sqlite3StrICmp(pExpr->u.zToken,"max")==0 ){
+ return WHERE_ORDERBY_MAX;
+ }
+ return WHERE_ORDERBY_NORMAL;
}
/*
** The select statement passed as the first argument is an aggregate query.
** The second argment is the associated aggregate-info object. This
@@ -97786,11 +97567,10 @@
int i, j, k;
SrcList *pTabList;
ExprList *pEList;
struct SrcList_item *pFrom;
sqlite3 *db = pParse->db;
- Expr *pE, *pRight, *pExpr;
if( db->mallocFailed ){
return WRC_Abort;
}
if( NEVER(p->pSrc==0) || (p->selFlags & SF_Expanded)!=0 ){
@@ -97872,11 +97652,11 @@
**
** The first loop just checks to see if there are any "*" operators
** that need expanding.
*/
for(k=0; knExpr; k++){
- pE = pEList->a[k].pExpr;
+ Expr *pE = pEList->a[k].pExpr;
if( pE->op==TK_ALL ) break;
assert( pE->op!=TK_DOT || pE->pRight!=0 );
assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) );
if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break;
}
@@ -97890,22 +97670,14 @@
ExprList *pNew = 0;
int flags = pParse->db->flags;
int longNames = (flags & SQLITE_FullColNames)!=0
&& (flags & SQLITE_ShortColNames)==0;
- /* When processing FROM-clause subqueries, it is always the case
- ** that full_column_names=OFF and short_column_names=ON. The
- ** sqlite3ResultSetOfSelect() routine makes it so. */
- assert( (p->selFlags & SF_NestedFrom)==0
- || ((flags & SQLITE_FullColNames)==0 &&
- (flags & SQLITE_ShortColNames)!=0) );
-
for(k=0; knExpr; k++){
- pE = a[k].pExpr;
- pRight = pE->pRight;
- assert( pE->op!=TK_DOT || pRight!=0 );
- if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){
+ Expr *pE = a[k].pExpr;
+ assert( pE->op!=TK_DOT || pE->pRight!=0 );
+ if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pE->pRight->op!=TK_ALL) ){
/* This particular expression does not need to be expanded.
*/
pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
if( pNew ){
pNew->a[pNew->nExpr-1].zName = a[k].zName;
@@ -97916,56 +97688,44 @@
a[k].pExpr = 0;
}else{
/* This expression is a "*" or a "TABLE.*" and needs to be
** expanded. */
int tableSeen = 0; /* Set to 1 when TABLE matches */
- char *zTName = 0; /* text of name of TABLE */
+ char *zTName; /* text of name of TABLE */
if( pE->op==TK_DOT ){
assert( pE->pLeft!=0 );
assert( !ExprHasProperty(pE->pLeft, EP_IntValue) );
zTName = pE->pLeft->u.zToken;
+ }else{
+ zTName = 0;
}
for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){
Table *pTab = pFrom->pTab;
- Select *pSub = pFrom->pSelect;
char *zTabName = pFrom->zAlias;
- const char *zSchemaName = 0;
- int iDb;
if( zTabName==0 ){
zTabName = pTab->zName;
}
if( db->mallocFailed ) break;
- if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){
- pSub = 0;
- if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
- continue;
- }
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*";
- }
+ if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
+ continue;
+ }
+ tableSeen = 1;
for(j=0; jnCol; j++){
+ Expr *pExpr, *pRight;
char *zName = pTab->aCol[j].zName;
char *zColname; /* The computed column name */
char *zToFree; /* Malloced string that needs to be freed */
Token sColname; /* Computed column name as a token */
- assert( zName );
- if( zTName && pSub
- && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0
- ){
- continue;
- }
-
/* If a column is marked as 'hidden' (currently only possible
** for virtual tables), do not include it in the expanded
** result-set list.
*/
if( IsHiddenColumn(&pTab->aCol[j]) ){
assert(IsVirtual(pTab));
continue;
}
- tableSeen = 1;
if( i>0 && zTName==0 ){
if( (pFrom->jointype & JT_NATURAL)!=0
&& tableAndColumnIndex(pTabList, i, zName, 0, 0)
){
@@ -97984,14 +97744,10 @@
zToFree = 0;
if( longNames || pTabList->nSrc>1 ){
Expr *pLeft;
pLeft = sqlite3Expr(db, TK_ID, zTabName);
pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
- if( zSchemaName ){
- pLeft = sqlite3Expr(db, TK_ID, zSchemaName);
- pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr, 0);
- }
if( longNames ){
zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName);
zToFree = zColname;
}
}else{
@@ -97999,22 +97755,10 @@
}
pNew = sqlite3ExprListAppend(pParse, pNew, pExpr);
sColname.z = zColname;
sColname.n = sqlite3Strlen30(zColname);
sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
- if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){
- struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
- if( pSub ){
- pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan);
- testcase( pX->zSpan==0 );
- }else{
- pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s",
- zSchemaName, zTabName, zColname);
- testcase( pX->zSpan==0 );
- }
- pX->bSpanIsTab = 1;
- }
sqlite3DbFree(db, zToFree);
}
}
if( !tableSeen ){
if( zTName ){
@@ -99068,21 +98812,15 @@
** index or indices to use) should place a different priority on
** satisfying the 'ORDER BY' clause than it does in other cases.
** Refer to code and comments in where.c for details.
*/
ExprList *pMinMax = 0;
- u8 flag = WHERE_ORDERBY_NORMAL;
-
- assert( p->pGroupBy==0 );
- assert( flag==0 );
- if( p->pHaving==0 ){
- flag = minMaxQuery(&sAggInfo, &pMinMax);
- }
- assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) );
-
+ u8 flag = minMaxQuery(p);
if( flag ){
- pMinMax = sqlite3ExprListDup(db, pMinMax, 0);
+ assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) );
+ assert( p->pEList->a[0].pExpr->x.pList->nExpr==1 );
+ pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->x.pList,0);
pDel = pMinMax;
if( pMinMax && !db->mallocFailed ){
pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0;
pMinMax->a[0].pExpr->op = TK_COLUMN;
}
@@ -102966,11 +102704,11 @@
#define WHERE_COLUMN_RANGE 0x00020000 /* xEXPR */
#define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */
#define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */
#define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */
#define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */
-#define WHERE_IN_ABLE 0x080f1000 /* Able to support an IN operator */
+#define WHERE_IN_ABLE 0x000f1000 /* Able to support an IN operator */
#define WHERE_TOP_LIMIT 0x00100000 /* xEXPR or x>=EXPR constraint */
#define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and xa; inTerm; i++, pTerm++){
if( pTerm->leftCursor != pSrc->iCursor ) continue;
assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
testcase( pTerm->eOperator==WO_IN );
testcase( pTerm->eOperator==WO_ISNULL );
- if( pTerm->eOperator & (WO_ISNULL) ) continue;
+ if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
if( pTerm->wtFlags & TERM_VNULL ) continue;
nTerm++;
}
/* If the ORDER BY clause contains only columns in the current
@@ -104818,32 +104556,29 @@
*(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy;
*(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage =
pUsage;
for(i=j=0, pTerm=pWC->a; inTerm; i++, pTerm++){
- u8 op;
if( pTerm->leftCursor != pSrc->iCursor ) continue;
assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
testcase( pTerm->eOperator==WO_IN );
testcase( pTerm->eOperator==WO_ISNULL );
- if( pTerm->eOperator & (WO_ISNULL) ) continue;
+ if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
if( pTerm->wtFlags & TERM_VNULL ) continue;
pIdxCons[j].iColumn = pTerm->u.leftColumn;
pIdxCons[j].iTermOffset = i;
- op = (u8)pTerm->eOperator;
- if( op==WO_IN ) op = WO_EQ;
- pIdxCons[j].op = op;
+ pIdxCons[j].op = (u8)pTerm->eOperator;
/* The direct assignment in the previous line is possible only because
** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
** following asserts verify this fact. */
assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
- assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
+ assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
j++;
}
for(i=0; ia[i].pExpr;
pIdxOrderBy[i].iColumn = pExpr->iColumn;
@@ -104925,11 +104660,10 @@
struct sqlite3_index_constraint *pIdxCons;
struct sqlite3_index_constraint_usage *pUsage;
WhereTerm *pTerm;
int i, j;
int nOrderBy;
- int bAllowIN; /* Allow IN optimizations */
double rCost;
/* Make sure wsFlags is initialized to some sane value. Otherwise, if the
** malloc in allocateIndexInfo() fails and this function returns leaving
** wsFlags in an uninitialized state, the caller may behave unpredictably.
@@ -104960,91 +104694,63 @@
** sqlite3ViewGetColumnNames() would have picked up the error.
*/
assert( pTab->azModuleArg && pTab->azModuleArg[0] );
assert( sqlite3GetVTable(pParse->db, pTab) );
- /* Try once or twice. On the first attempt, allow IN optimizations.
- ** If an IN optimization is accepted by the virtual table xBestIndex
- ** method, but the pInfo->aConstrainUsage.omit flag is not set, then
- ** the query will not work because it might allow duplicate rows in
- ** output. In that case, run the xBestIndex method a second time
- ** without the IN constraints. Usually this loop only runs once.
- ** The loop will exit using a "break" statement.
- */
- for(bAllowIN=1; 1; bAllowIN--){
- assert( bAllowIN==0 || bAllowIN==1 );
-
- /* Set the aConstraint[].usable fields and initialize all
- ** output variables to zero.
- **
- ** aConstraint[].usable is true for constraints where the right-hand
- ** side contains only references to tables to the left of the current
- ** table. In other words, if the constraint is of the form:
- **
- ** column = expr
- **
- ** and we are evaluating a join, then the constraint on column is
- ** only valid if all tables referenced in expr occur to the left
- ** of the table containing column.
- **
- ** The aConstraints[] array contains entries for all constraints
- ** on the current table. That way we only have to compute it once
- ** even though we might try to pick the best index multiple times.
- ** For each attempt at picking an index, the order of tables in the
- ** join might be different so we have to recompute the usable flag
- ** each time.
- */
- pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
- pUsage = pIdxInfo->aConstraintUsage;
- for(i=0; inConstraint; i++, pIdxCons++){
- j = pIdxCons->iTermOffset;
- pTerm = &pWC->a[j];
- if( (pTerm->prereqRight&p->notReady)==0
- && (bAllowIN || pTerm->eOperator!=WO_IN)
- ){
- pIdxCons->usable = 1;
- }else{
- pIdxCons->usable = 0;
- }
- }
- memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
- if( pIdxInfo->needToFreeIdxStr ){
- sqlite3_free(pIdxInfo->idxStr);
- }
- pIdxInfo->idxStr = 0;
- pIdxInfo->idxNum = 0;
- pIdxInfo->needToFreeIdxStr = 0;
- pIdxInfo->orderByConsumed = 0;
- /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
- pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
- nOrderBy = pIdxInfo->nOrderBy;
- if( !p->pOrderBy ){
- pIdxInfo->nOrderBy = 0;
- }
-
- if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
- return;
- }
-
- pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
- for(i=0; inConstraint; i++, pIdxCons++){
- if( pUsage[i].argvIndex>0 ){
- j = pIdxCons->iTermOffset;
- pTerm = &pWC->a[j];
- p->cost.used |= pTerm->prereqRight;
- if( pTerm->eOperator==WO_IN && pUsage[i].omit==0 ){
- /* Do not attempt to use an IN constraint if the virtual table
- ** says that the equivalent EQ constraint cannot be safely omitted.
- ** If we do attempt to use such a constraint, some rows might be
- ** repeated in the output. */
- break;
- }
- }
- }
- if( i>=pIdxInfo->nConstraint ) break;
- }
-
+ /* Set the aConstraint[].usable fields and initialize all
+ ** output variables to zero.
+ **
+ ** aConstraint[].usable is true for constraints where the right-hand
+ ** side contains only references to tables to the left of the current
+ ** table. In other words, if the constraint is of the form:
+ **
+ ** column = expr
+ **
+ ** and we are evaluating a join, then the constraint on column is
+ ** only valid if all tables referenced in expr occur to the left
+ ** of the table containing column.
+ **
+ ** The aConstraints[] array contains entries for all constraints
+ ** on the current table. That way we only have to compute it once
+ ** even though we might try to pick the best index multiple times.
+ ** For each attempt at picking an index, the order of tables in the
+ ** join might be different so we have to recompute the usable flag
+ ** each time.
+ */
+ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
+ pUsage = pIdxInfo->aConstraintUsage;
+ for(i=0; inConstraint; i++, pIdxCons++){
+ j = pIdxCons->iTermOffset;
+ pTerm = &pWC->a[j];
+ pIdxCons->usable = (pTerm->prereqRight&p->notReady) ? 0 : 1;
+ }
+ memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
+ if( pIdxInfo->needToFreeIdxStr ){
+ sqlite3_free(pIdxInfo->idxStr);
+ }
+ pIdxInfo->idxStr = 0;
+ pIdxInfo->idxNum = 0;
+ pIdxInfo->needToFreeIdxStr = 0;
+ pIdxInfo->orderByConsumed = 0;
+ /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
+ pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
+ nOrderBy = pIdxInfo->nOrderBy;
+ if( !p->pOrderBy ){
+ pIdxInfo->nOrderBy = 0;
+ }
+
+ if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
+ return;
+ }
+
+ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
+ for(i=0; inConstraint; i++){
+ if( pUsage[i].argvIndex>0 ){
+ p->cost.used |= pWC->a[pIdxCons[i].iTermOffset].prereqRight;
+ }
+ }
+
/* If there is an ORDER BY clause, and the selected virtual table index
** does not satisfy it, increase the cost of the scan accordingly. This
** matches the processing for non-virtual tables in bestBtreeIndex().
*/
rCost = pIdxInfo->estimatedCost;
@@ -106015,11 +105721,11 @@
int bRev = 2;
WHERETRACE((" --> before isSortingIndex: nPriorSat=%d\n",nPriorSat));
pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev);
WHERETRACE((" --> after isSortingIndex: bRev=%d nOBSat=%d\n",
bRev, pc.plan.nOBSat));
- if( nPriorSatplan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
/* Case 0: The table is a virtual-table. Use the VFilter and VNext
** to access the data.
*/
int iReg; /* P3 Value for OP_VFilter */
- int addrNotFound;
sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
int nConstraint = pVtabIdx->nConstraint;
struct sqlite3_index_constraint_usage *aUsage =
pVtabIdx->aConstraintUsage;
const struct sqlite3_index_constraint *aConstraint =
pVtabIdx->aConstraint;
sqlite3ExprCachePush(pParse);
iReg = sqlite3GetTempRange(pParse, nConstraint+2);
- addrNotFound = pLevel->addrBrk;
for(j=1; j<=nConstraint; j++){
for(k=0; ka[aConstraint[k].iTermOffset];
- int iTarget = iReg+j+1;
- if( pTerm->eOperator & WO_IN ){
- codeEqualityTerm(pParse, pTerm, pLevel, iTarget);
- addrNotFound = pLevel->addrNxt;
- }else{
- sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
- }
+ int iTerm = aConstraint[k].iTermOffset;
+ sqlite3ExprCode(pParse, pWC->a[iTerm].pExpr->pRight, iReg+j+1);
break;
}
}
if( k==nConstraint ) break;
}
sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg);
sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
- sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr,
+ sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrBrk, iReg, pVtabIdx->idxStr,
pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC);
pVtabIdx->needToFreeIdxStr = 0;
for(j=0; jnSrc==1 ){
- yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
- if( yygotominor.yy347 ){
- struct SrcList_item *pNew = &yygotominor.yy347->a[yygotominor.yy347->nSrc-1];
- struct SrcList_item *pOld = yymsp[-4].minor.yy347->a;
- pNew->zName = pOld->zName;
- pNew->zDatabase = pOld->zDatabase;
- pOld->zName = pOld->zDatabase = 0;
- }
- sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy347);
}else{
Select *pSubquery;
sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347);
- pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,SF_NestedFrom,0,0);
+ pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,0,0,0);
yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
}
}
break;
case 137: /* dbnm ::= */
@@ -111008,11 +110691,11 @@
if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
}
yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0);
spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
- if( yymsp[-2].minor.yy305 && yygotominor.yy342.pExpr ){
+ if( yymsp[-2].minor.yy392 && yygotominor.yy342.pExpr ){
yygotominor.yy342.pExpr->flags |= EP_Distinct;
}
}
break;
case 197: /* expr ::= ID LP STAR RP */
Index: SQLite.Interop/src/core/sqlite3.h
==================================================================
--- SQLite.Interop/src/core/sqlite3.h
+++ SQLite.Interop/src/core/sqlite3.h
@@ -105,13 +105,13 @@
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.7.16"
-#define SQLITE_VERSION_NUMBER 3007016
-#define SQLITE_SOURCE_ID "2013-01-04 19:22:33 8285b15a058811a9a8b452837f52e6a065868115"
+#define SQLITE_VERSION "3.7.15.2"
+#define SQLITE_VERSION_NUMBER 3007015
+#define SQLITE_SOURCE_ID "2013-01-09 11:53:05 c0e09560d26f0a6456be9dd3447f5311eb4f238f"
/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version, sqlite3_sourceid
**
Index: readme.htm
==================================================================
--- readme.htm
+++ readme.htm
@@ -3,12 +3,12 @@
ADO.NET SQLite Data Provider
-Version 1.0.84.0 March XX, 2013 (release scheduled)
-Using SQLite 3.7.16
+Version 1.0.84.0 January 9, 2013
+Using SQLite 3.7.15.2
Originally written by Robert Simpson
Released to the public domain, use at your own risk!
Official provider website: http://system.data.sqlite.org/
Legacy versions: http://sqlite.phxsoftware.com/
@@ -185,14 +185,15 @@
Version History
- 1.0.84.0 - March XX, 2013 (release scheduled)
+ 1.0.84.0 - January 9, 2013
- - Updated to SQLite 3.7.16.
+ - Updated to SQLite 3.7.15.2.
+ - Explicitly dispose of all SQLiteCommand objects managed by the DbDataAdapter class. Fix for [6434e23a0f].
- Add Cancel method to the SQLiteConnection class to interrupt a long running query.
- Improve thread safety of the SQLiteLog.LogMessage method.
1.0.83.0 - December 29, 2012
Index: www/news.wiki
==================================================================
--- www/news.wiki
+++ www/news.wiki
@@ -1,14 +1,15 @@
News
Version History
- 1.0.84.0 - March XX, 2013 (release scheduled)
+ 1.0.84.0 - January 9, 2013
- - Updated to SQLite 3.7.16.
+ - Updated to SQLite 3.7.15.2.
+ - Explicitly dispose of all SQLiteCommand objects managed by the DbDataAdapter class. Fix for [6434e23a0f].
- Add Cancel method to the SQLiteConnection class to interrupt a long running query.
- Improve thread safety of the SQLiteLog.LogMessage method.
1.0.83.0 - December 29, 2012