Index: main.mk ================================================================== --- main.mk +++ main.mk @@ -50,11 +50,11 @@ OPTS += -DHAVE_MALLOC_USABLE_SIZE OPTS += -DHAVE_USLEEP #OPTS += -DSQLITE4_MEMDEBUG=1 #OPTS += -DSQLITE4_NO_SYNC=1 -DLSM_NO_SYNC=1 #OPTS += -DSQLITE4_OMIT_ANALYZE -#OPTS += -DSQLITE4_OMIT_AUTOMATIC_INDEX +OPTS += -DSQLITE4_OMIT_AUTOMATIC_INDEX OPTS += -DSQLITE4_OMIT_VIRTUALTABLE=1 OPTS += -DSQLITE4_OMIT_XFER_OPT OPTS += -DSQLITE4_THREADSAFE=0 # This is how we compile Index: src/alter.c ================================================================== --- src/alter.c +++ src/alter.c @@ -526,12 +526,12 @@ "ELSE sqlite_rename_table(sql, %Q) END, " #endif "tbl_name = %Q, " "name = CASE " "WHEN type='table' THEN %Q " - "WHEN name LIKE 'sqlite_%%_unique%%' AND type='index' THEN " - "'sqlite_' || %Q || substr(name,%d+8) " + "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN " + "'sqlite_autoindex_' || %Q || substr(name,%d+18) " "ELSE name END " "WHERE tbl_name=%Q AND " "(type='table' OR type='index' OR type='trigger');", zDb, SCHEMA_TABLE(iDb), zName, zName, zName, #ifndef SQLITE4_OMIT_TRIGGER @@ -637,11 +637,11 @@ /* Check that the new column is not specified as PRIMARY KEY or UNIQUE. ** If there is a NOT NULL constraint, then the default value for the ** column must not be NULL. */ - if( pCol->iPrimKey>0 ){ + if( pCol->isPrimKey ){ sqlite4ErrorMsg(pParse, "Cannot add a PRIMARY KEY column"); return; } if( pNew->pIndex ){ sqlite4ErrorMsg(pParse, "Cannot add a UNIQUE column"); Index: src/analyze.c ================================================================== --- src/analyze.c +++ src/analyze.c @@ -49,19 +49,19 @@ ** rows in the table identified by sqlite_stat1.tbl. ** ** Format for sqlite_stat3: ** ** The sqlite_stat3 table may contain multiple entries for each index. -** The idx column names the index and the tbl column contains the name -** of the indexed table. If the idx and tbl columns are the same, then the -** sample is of the PRIMARY KEY index. The sample column is a value taken -** from the left-most column of the index encoded using the key-encoding. -** The nEq column is the approximate number of entires in the index whose -** left-most column exactly matches the sample. nLt is the approximate -** number of entires whose left-most column is less than the sample. The -** nDLt column is the approximate number of distinct left-most entries in -** the index that are less than the sample. +** The idx column names the index and the tbl column is the table of the +** index. If the idx and tbl columns are the same, then the sample is +** of the INTEGER PRIMARY KEY. The sample column is a value taken from +** the left-most column of the index. The nEq column is the approximate +** number of entires in the index whose left-most column exactly matches +** the sample. nLt is the approximate number of entires whose left-most +** column is less than the sample. The nDLt column is the approximate +** number of distinct left-most entries in the index that are less than +** the sample. ** ** Future versions of SQLite might change to store a string containing ** multiple integers values in the nDLt column of sqlite_stat3. The first ** integer will be the number of prior index entries that are distinct in ** the left-most column. The second integer will be the number of prior index @@ -151,11 +151,11 @@ if( zWhere ){ sqlite4NestedParse(pParse, "DELETE FROM %Q.%s WHERE %s=%Q", pDb->zName, zTab, zWhereType, zWhere ); }else{ - /* The sqlite_stat[13] table already exists. Delete all rows. */ + /* The sqlite_stat[12] table already exists. Delete all rows. */ sqlite4VdbeAddOp2(v, OP_Clear, aRoot[i], iDb); } } } @@ -189,31 +189,23 @@ u32 iPrn; /* Pseudo-random number used for sampling */ struct Stat3Sample { void *pKey; /* Index key for this sample */ int nKey; /* Bytes of pKey in use */ int nAlloc; /* Bytes of space allocated at pKey */ + tRowcnt nEq; /* sqlite_stat3.nEq */ tRowcnt nLt; /* sqlite_stat3.nLt */ tRowcnt nDLt; /* sqlite_stat3.nDLt */ u8 isPSample; /* True if a periodic sample */ - u32 iHash; /* Tiebreaker value (pseudo-random) */ + u32 iHash; /* Tiebreaker hash */ } *a; /* An array of samples */ }; #ifdef SQLITE4_ENABLE_STAT3 -/* -** Delete a Stat3Accum object. -*/ -static void delStat3Accum(void *pCtx, void *pDel){ +static void delStat3Accum(void *pCtx, void *p){ sqlite4 *db = (sqlite4*)pCtx; - Stat3Accum *p = (Stat3Accum*)pDel; - int i; - - for(i=0; inSample; i++){ - sqlite4DbFree(db, p->a[i].pKey); - } sqlite4DbFree(db, p); } /* ** Implementation of the stat3_init(C,S) SQL function. The two parameters @@ -304,18 +296,14 @@ doInsert = 1; } } if( !doInsert ) return; if( p->nSample==p->mxSample ){ - void *pKey = p->a[iMin].pKey; - int nAlloc = p->a[iMin].nAlloc; assert( p->nSample - iMin - 1 >= 0 ); memmove(&p->a[iMin], &p->a[iMin+1], sizeof(p->a[0])*(p->nSample-iMin-1)); pSample = &p->a[p->nSample-1]; memset(pSample, 0, sizeof(struct Stat3Sample)); - pSample->pKey = pKey; - pSample->nAlloc = nAlloc; }else{ pSample = &p->a[p->nSample++]; } pKey = sqlite4_value_blob(argv[3], &nKey); @@ -419,10 +407,13 @@ "stat3_get", /* zName */ 0, /* pHash */ 0 /* pDestructor */ }; #endif /* SQLITE4_ENABLE_STAT3 */ + + + /* ** Generate code to do an analysis of all indices associated with ** a single table. */ @@ -488,10 +479,11 @@ iIdxCur = pParse->nTab++; sqlite4VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int nCol; KeyInfo *pKey; + int *aChngAddr; /* Array of jump instruction addresses */ int regCnt; /* Total number of rows in table. */ int regPrev; /* Previous index key read from database */ int aregCard; /* Cardinality array registers */ #ifdef SQLITE4_ENABLE_STAT3 int addrAddimm; /* Address at top of stat3 output loop */ @@ -499,10 +491,12 @@ #endif if( pOnlyIdx && pOnlyIdx!=pIdx ) continue; VdbeNoopComment((v, "Begin analysis of %s", pIdx->zName)); nCol = pIdx->nColumn; + aChngAddr = sqlite4DbMallocRaw(db, sizeof(int)*nCol); + if( aChngAddr==0 ) continue; pKey = sqlite4IndexKeyinfo(pParse, pIdx); if( iMem+1+(nCol*2)>pParse->nMem ){ pParse->nMem = iMem+1+(nCol*2); } @@ -552,13 +546,11 @@ regPrev = iMem+1; aregCard = iMem+2; sqlite4VdbeAddOp2(v, OP_Integer, 0, regCnt); sqlite4VdbeAddOp2(v, OP_Null, 0, regPrev); -#ifdef SQLITE4_ENABLE_STAT3 sqlite4VdbeAddOp2(v, OP_Null, 0, regSample); -#endif for(i=0; inMemnMem = regRec; sqlite4VdbeJumpHere(v, jZeroRows); } + /* ** Generate code that will cause the most recent index analysis to ** be loaded into internal hash tables where is can be used. */ Index: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -145,11 +145,11 @@ int maxTab = 1; pSchema = pParse->db->aDb[iDb].pSchema; for(p=sqliteHashFirst(&pSchema->idxHash); p;p=sqliteHashNext(p)){ Index *pIdx = (Index*)sqliteHashData(p); - if( pIdx->tnum!=KVSTORE_ROOT && pIdx->tnum > maxTab ) maxTab = pIdx->tnum; + if( pIdx->tnum > maxTab ) maxTab = pIdx->tnum; } pParse->iNewidxReg = ++pParse->nMem; sqlite4VdbeAddOp2(v, OP_Integer, maxTab, pParse->iNewidxReg); } @@ -821,11 +821,12 @@ sqlite4VdbeAddOp2(v, OP_Integer, tnum, reg2); } #endif sqlite4OpenMasterTable(pParse, iDb); sqlite4VdbeAddOp2(v, OP_NewRowid, 0, reg1); - sqlite4VdbeAddOp3(v, OP_Insert, 0, 0, reg1); + sqlite4VdbeAddOp2(v, OP_Null, 0, reg3); + sqlite4VdbeAddOp3(v, OP_Insert, 0, reg3, reg1); sqlite4VdbeChangeP5(v, OPFLAG_APPEND); sqlite4VdbeAddOp0(v, OP_Close); } /* Normal (non-error) return. */ @@ -1058,27 +1059,29 @@ goto primary_key_exit; } pTab->tabFlags |= TF_HasPrimaryKey; if( pList==0 ){ iCol = pTab->nCol - 1; - pTab->aCol[iCol].iPrimKey = 1; + pTab->aCol[iCol].isPrimKey = 1; pTab->aCol[iCol].notNull = 1; }else{ for(i=0; inExpr; i++){ for(iCol=0; iColnCol; iCol++){ if( sqlite4_stricmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){ break; } } if( iColnCol ){ - pTab->aCol[iCol].iPrimKey = i+1; + pTab->aCol[iCol].isPrimKey = i+1; pTab->aCol[iCol].notNull = 1; } } if( pList->nExpr>1 ) iCol = -1; } - pPk = sqlite4CreateIndex(pParse, 0, pList, 0, onError, 0, sortOrder, 1); + pPk = sqlite4CreateIndex( + pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder, 0, 1 + ); if( iCol>=0 && iColnCol && (zType = pTab->aCol[iCol].zType)!=0 && sqlite4_stricmp(zType, "INTEGER")==0 && sortOrder==SQLITE4_SO_ASC @@ -1336,11 +1339,10 @@ static Index *newIndex( Parse *pParse, /* Parse context for current statement */ Table *pTab, /* Table index is created on */ const char *zName, /* Name of index object to create */ int nCol, /* Number of columns in index */ - int nCover, /* Number of covered columns in index */ int onError, /* One of OE_Abort, OE_Replace etc. */ int nExtra, /* Bytes of extra space to allocate */ char **pzExtra /* OUT: Pointer to extra space */ ){ sqlite4 *db = pParse->db; /* Database handle */ @@ -1353,11 +1355,10 @@ pIndex = sqlite4DbMallocZero(db, ROUND8(sizeof(Index)) + /* Index structure */ ROUND8(sizeof(tRowcnt)*(nCol+1)) + /* Index.aiRowEst */ sizeof(char *)*nCol + /* Index.azColl */ sizeof(int)*nCol + /* Index.aiColumn */ - sizeof(int)*nCover + /* Index.aiCover */ sizeof(u8)*nCol + /* Index.aSortOrder */ nName + 1 + /* Index.zName */ nExtra /* Collation sequence names */ ); assert( pIndex || db->mallocFailed ); @@ -1368,20 +1369,19 @@ pIndex->azColl = (char**) ((char*)pIndex->aiRowEst + ROUND8(sizeof(tRowcnt)*nCol+1)); assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowEst) ); assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) ); pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]); - pIndex->aiCover = (int *)(&pIndex->aiColumn[nCol]); - pIndex->aSortOrder = (u8 *)(&pIndex->aiCover[nCover]); + pIndex->aSortOrder = (u8 *)(&pIndex->aiColumn[nCol]); pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]); zExtra = (char *)(&pIndex->zName[nName+1]); memcpy(pIndex->zName, zName, nName+1); pIndex->pTable = pTab; pIndex->nColumn = nCol; - pIndex->nCover = nCover; pIndex->onError = (u8)onError; pIndex->pSchema = pTab->pSchema; + } *pzExtra = zExtra; return pIndex; } @@ -1416,11 +1416,11 @@ Index *pIndex; /* New index */ char *zExtra; assert( !pTab->pIndex || pTab->pIndex->eIndexType!=SQLITE4_INDEX_PRIMARYKEY ); assert( sqlite4Strlen30("binary")==6 ); - pIndex = newIndex(pParse, pTab, pTab->zName, 1, 0, OE_Abort, 1+6, &zExtra); + pIndex = newIndex(pParse, pTab, pTab->zName, 1, OE_Abort, 1+6, &zExtra); if( pIndex && addIndexToHash(db, pIndex) ){ sqlite4DbFree(db, pIndex); pIndex = 0; } if( pIndex ){ @@ -2234,35 +2234,10 @@ assert( isDeferred==0 || isDeferred==1 ); /* EV: R-30323-21917 */ pFKey->isDeferred = (u8)isDeferred; #endif } -/* -** Cursor iPkCsr is open on a primary key index. This function generates -** code that creates the corresponding covering index record required -** by pIdx by reading values from this cursor. The record is stored in -** register regOut. -*/ -void sqlite4EncodeIndexValue( - Parse *pParse, /* Parse context */ - int iPkCsr, /* Cursor open on primary key */ - Index *pIdx, /* Index to create record for */ - int regOut /* Register to write record to */ -){ - Vdbe *v = pParse->pVdbe; /* Generate code into this virtual machine */ - Table *pTab = pIdx->pTable; /* The table that is indexed */ - int i; /* Used to iterate through columns */ - int reg; /* Array of pIdx->nCover temp registers */ - - reg = sqlite4GetTempRange(pParse, pIdx->nCover); - for(i=0; inCover; i++){ - sqlite4ExprCodeGetColumnOfTable(v, pTab, iPkCsr, pIdx->aiCover[i], reg+i); - } - sqlite4VdbeAddOp3(v, OP_MakeRecord, reg, pIdx->nCover, regOut); - sqlite4ReleaseTempRange(pParse, reg, pIdx->nCover); -} - /* ** Generate code that will erase and refill index *pIdx. This is ** used to initialize a newly created index or to recompute the ** content of an index in response to a REINDEX command. */ @@ -2316,31 +2291,27 @@ for(i=0; inCol; i++){ sqlite4VdbeAddOp3(v, OP_Column, iTab, i, regData+i); } sqlite4Fts5CodeUpdate(pParse, pIdx, pParse->iNewidxReg, regKey, regData, 0); }else{ - int regData = 0; - regKey = sqlite4GetTempRange(pParse, 2); + sqlite4GetTempRange(pParse,2); + regKey = sqlite4GetTempReg(pParse); sqlite4EncodeIndexKey(pParse, pPk, iTab, pIdx, iIdx, 0, regKey); if( pIdx->onError!=OE_None ){ const char *zErr = "indexed columns are not unique"; int addrTest; addrTest = sqlite4VdbeAddOp4Int(v, OP_IsUnique, iIdx, 0, regKey, 0); sqlite4HaltConstraint(pParse, OE_Abort, (char *)zErr, P4_STATIC); sqlite4VdbeJumpHere(v, addrTest); } - if( pIdx->nCover>0 ){ - regData = regKey+1; - sqlite4EncodeIndexValue(pParse, iTab, pIdx, regData); - } - sqlite4VdbeAddOp3(v, OP_Insert, iIdx, regData, regKey); - sqlite4ReleaseTempRange(pParse, regKey, 2); + sqlite4VdbeAddOp3(v, OP_IdxInsert, iIdx, 0, regKey); } sqlite4VdbeAddOp2(v, OP_Next, iTab, addr1+1); sqlite4VdbeJumpHere(v, addr1); + sqlite4ReleaseTempReg(pParse, regKey); sqlite4VdbeAddOp1(v, OP_Close, iTab); sqlite4VdbeAddOp1(v, OP_Close, iIdx); } @@ -2418,17 +2389,15 @@ } /* Ensure that the proposed index name is not reserved. */ assert( pName->z!=0 ); zName = sqlite4NameFromToken(db, pName); - if( zName==0 || sqlite4CheckObjectName(pParse, zName) ){ - pTab = 0; - } + if( zName==0 || sqlite4CheckObjectName(pParse, zName) ) return 0; /* Unless SQLite is currently parsing an existing database schema, check ** that there is not already an index or table using the proposed name. */ - else if( !db->init.busy ){ + if( !db->init.busy ){ char *zDb = db->aDb[iDb].zName; if( sqlite4FindTable(db, zName, zDb)!=0 ){ sqlite4ErrorMsg(pParse, "there is already a table named %s", zName); } else if( sqlite4FindIndex(db, zName, zDb)!=0 ){ @@ -2574,11 +2543,11 @@ pTab = createIndexFindTable(pParse, p, &pIdxName, &zIdx, &iDb); if( pTab && 0==createIndexAuth(pParse, pTab, zIdx) ){ int nExtra = sqlite4Fts5IndexSz(); char *zExtra = 0; - pIdx = newIndex(pParse, pTab, zIdx, 0, 0, 0, nExtra, &zExtra); + pIdx = newIndex(pParse, pTab, zIdx, 0, 0, nExtra, &zExtra); if( pIdx ){ pIdx->pFts = (Fts5Index *)zExtra; sqlite4Fts5IndexInit(pParse, pIdx, pList); pIdx->eIndexType = SQLITE4_INDEX_FTS5; } @@ -2603,33 +2572,10 @@ sqlite4ExprListDelete(db, pList); sqlite4SrcListDelete(db, p->pTblName); } -/* -** Parameter zName points to a nul-terminated buffer containing a column -** name. If table pTab has a column of the specified name, return its -** index (the first table column being 0, the next 1 etc.). Or, if there -** is no such column, leave an error in pParse and return -1. -*/ -static int findTableColumn(Parse *pParse, Table *pTab, const char *zName){ - int j; - Column *pTabCol; - - for(j=0, pTabCol=pTab->aCol; jnCol; j++, pTabCol++){ - if( sqlite4_stricmp(zName, pTabCol->zName)==0 ) break; - } - if( j>=pTab->nCol ){ - sqlite4ErrorMsg(pParse, "table %s has no column named %s", - pTab->zName, zName); - pParse->checkSchema = 1; - return -1; - } - - return j; -} - /* ** Create a new index for an SQL table. pName1.pName2 is the name of the index ** and pTblList is the name of the table that is to be indexed. Both will ** be NULL for a primary key or an index that is created to satisfy a ** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable @@ -2644,16 +2590,19 @@ ** structure. This is used by sqlite4AddPrimaryKey() to mark the index ** as the tables primary key (Index.autoIndex==2). */ Index *sqlite4CreateIndex( Parse *pParse, /* All information about this parse */ - CreateIndex *pCI, /* Name of index to create etc. */ + Token *pName1, /* First part of index name. May be NULL */ + Token *pName2, /* Second part of index name. May be NULL */ + SrcList *pTblName, /* Table to index. Use pParse->pNewTable if 0 */ ExprList *pList, /* A list of columns to be indexed */ - IdList *pCovering, /* Covering list (or NULL) */ int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ + Token *pStart, /* The CREATE token that begins this statement */ Token *pEnd, /* The ")" that closes the CREATE INDEX statement */ int sortOrder, /* Sort order of primary key when pList==NULL */ + int ifNotExist, /* Omit error if index already exists */ int bPrimaryKey /* True to create the tables primary key */ ){ Index *pRet = 0; /* Pointer to return */ Table *pTab = 0; /* Table to be indexed */ Index *pIndex = 0; /* The index to be created */ @@ -2665,37 +2614,36 @@ Token *pName = 0; /* Unqualified name of the index to create */ ExprListItem *pListItem; /* For looping over pList */ int nExtra = 0; char *zExtra; - int nCover = 0; - Token *pStart = 0; - SrcList *pTblName = 0; - - if( pCI ){ - pStart = &pCI->tCreate; - pTblName = pCI->pTblName; - } - if( pCovering ){ - nCover = pCovering->nId; - if( nCover==0 ) nCover = pList->nExpr; - } - assert( pStart==0 || pEnd!=0 ); /* pEnd must be non-NULL if pStart is */ assert( pParse->nErr==0 ); /* Never called with prior errors */ if( db->mallocFailed || IN_DECLARE_VTAB ){ goto exit_create_index; } if( SQLITE4_OK!=sqlite4ReadSchema(pParse) ){ goto exit_create_index; } - /* Find the table that is to be indexed. Return early if not found. */ - if( pCI ){ - pTab = createIndexFindTable(pParse, pCI, &pName, &zName, &iDb); + /* + ** Find the table that is to be indexed. Return early if not found. + */ + if( pTblName!=0 ){ + CreateIndex sCreate; + sCreate.bUnique = onError; + sCreate.bIfnotexist = ifNotExist; + sCreate.tCreate = *pStart; + sCreate.tName1 = *pName1; + sCreate.tName2 = *pName2; + sCreate.pTblName = pTblName; + + pTab = createIndexFindTable(pParse, &sCreate, &pName, &zName, &iDb); if( !pTab ) goto exit_create_index; + }else{ + assert( pName==0 ); assert( pStart==0 ); pTab = pParse->pNewTable; if( !pTab ) goto exit_create_index; iDb = sqlite4SchemaToIndex(db, pTab->pSchema); @@ -2703,13 +2651,13 @@ assert( pTab!=0 ); assert( pParse->nErr==0 ); assert( IsVirtual(pTab)==0 && IsView(pTab)==0 ); - /* If pCI==0 it means that we are dealing with a PRIMARY KEY or + /* If pName==0 it means that we are dealing with a primary key or ** UNIQUE constraint. We have to invent our own name. */ - if( pCI==0 ){ + if( pName==0 ){ if( !bPrimaryKey ){ int n; Index *pLoop; for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){} zName = sqlite4MPrintf(db, "sqlite_%s_unique%d", pTab->zName, n); @@ -2756,13 +2704,11 @@ } } } /* Allocate the new Index structure. */ - pIndex = newIndex( - pParse, pTab, zName, pList->nExpr, nCover, onError, nExtra, &zExtra - ); + pIndex = newIndex(pParse, pTab, zName, pList->nExpr, onError, nExtra,&zExtra); if( !pIndex ) goto exit_create_index; assert( pIndex->eIndexType==SQLITE4_INDEX_USER ); if( pName==0 ){ if( bPrimaryKey ){ @@ -2779,15 +2725,23 @@ ** TODO: Add a test to make sure that the same column is not named ** more than once within the same index. Only the first instance of ** the column will ever be used by the optimizer. */ for(i=0, pListItem=pList->a; inExpr; i++, pListItem++){ + const char *zColName = pListItem->zName; + Column *pTabCol; char *zColl; /* Collation sequence name */ - j = findTableColumn(pParse, pTab, pListItem->zName); - if( j<0 ) goto exit_create_index; - + for(j=0, pTabCol=pTab->aCol; jnCol; j++, pTabCol++){ + if( sqlite4_stricmp(zColName, pTabCol->zName)==0 ) break; + } + if( j>=pTab->nCol ){ + sqlite4ErrorMsg(pParse, "table %s has no column named %s", + pTab->zName, zColName); + pParse->checkSchema = 1; + goto exit_create_index; + } pIndex->aiColumn[i] = j; if( pListItem->pExpr && pListItem->pExpr->pColl ){ int nColl; zColl = pListItem->pExpr->pColl->zName; nColl = sqlite4Strlen30(zColl) + 1; @@ -2808,21 +2762,10 @@ pIndex->azColl[i] = zColl; pIndex->aSortOrder[i] = (u8)pListItem->sortOrder; } sqlite4DefaultRowEst(pIndex); - /* Scan the names of any covered columns. */ - for(i=0; inId ){ - j = findTableColumn(pParse, pTab, pCovering->a[i].zName); - if( j<0 ) goto exit_create_index; - pIndex->aiCover[i] = j; - }else{ - pIndex->aiCover[i] = i; - } - } - if( pTab==pParse->pNewTable ){ /* This routine has been called to create an automatic index as a ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or ** a PRIMARY KEY or UNIQUE clause following the column definitions. ** i.e. one of: @@ -2947,11 +2890,10 @@ sqlite4DbFree(db, pIndex->zColAff); sqlite4DbFree(db, pIndex); } sqlite4ExprListDelete(db, pList); sqlite4SrcListDelete(db, pTblName); - sqlite4IdListDelete(db, pCovering); sqlite4DbFree(db, zName); return pRet; } /* @@ -3806,10 +3748,11 @@ nCol = pIdx->nColumn + (pPk ? pPk->nColumn : 0); nBytes = sizeof(KeyInfo) + (nCol-1)*sizeof(CollSeq*) + nCol; pKey = (KeyInfo *)sqlite4DbMallocZero(db, nBytes); if( pKey ){ + pKey->db = pParse->db; pKey->aSortOrder = (u8 *)&(pKey->aColl[nCol]); assert( &pKey->aSortOrder[nCol]==&(((u8 *)pKey)[nBytes]) ); for(i=0; inColumn; i++){ char *zColl = pIdx->azColl[i]; Index: src/ctime.c ================================================================== --- src/ctime.c +++ src/ctime.c @@ -296,10 +296,13 @@ #ifdef SQLITE4_OMIT_VIEW "OMIT_VIEW", #endif #ifdef SQLITE4_OMIT_VIRTUALTABLE "OMIT_VIRTUALTABLE", +#endif +#ifdef SQLITE4_OMIT_XFER_OPT + "OMIT_XFER_OPT", #endif #ifdef SQLITE4_PERFORMANCE_TRACE "PERFORMANCE_TRACE", #endif #ifdef SQLITE4_PROXY_DEBUG Index: src/delete.c ================================================================== --- src/delete.c +++ src/delete.c @@ -340,11 +340,11 @@ ** the scan is complete because deleting an item can change the scan ** order. */ sqlite4VdbeAddOp2(v, OP_Null, 0, regSet); VdbeComment((v, "initialize RowSet")); pWInfo = sqlite4WhereBegin( - pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK, 0 + pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK ); if( pWInfo==0 ) goto delete_from_cleanup; sqlite4VdbeAddOp2(v, OP_RowKey, iCur, regKey); sqlite4VdbeAddOp3(v, OP_RowSetAdd, regSet, 0, regKey); sqlite4WhereEnd(pWInfo); Index: src/env.c ================================================================== --- src/env.c +++ src/env.c @@ -87,10 +87,11 @@ ** thread to initialized the library in a multi-threaded system. Other ** threads should avoid using the sqlite4_env object until after it has ** completely initialized. */ int sqlite4_initialize(sqlite4_env *pEnv){ + MUTEX_LOGIC( sqlite4_mutex *pMaster; ) /* The main static mutex */ int rc; /* Result code */ if( pEnv==0 ) pEnv = &sqlite4DefaultEnv; /* If SQLite is already completely initialized, then this call @@ -177,11 +178,11 @@ sqlite4_mutex_free(pEnv->pMemMutex); pEnv->pMemMutex = 0; while( (pMkr = pEnv->pFactory)!=0 && pMkr->isPerm==0 ){ KVFactory *pNext = pMkr->pNext; sqlite4_free(pEnv, pMkr); - pEnv->pFactory = pNext; + pMkr = pNext; } sqlite4MutexEnd(pEnv); sqlite4MallocEnd(pEnv); pEnv->isInit = 0; } Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -1381,23 +1381,22 @@ sqlite4 *db = pParse->db; Table *pTab = p->pSrc->a[0].pTab; Expr *pRhs = p->pEList->a[0].pExpr; int iCol = pRhs->iColumn; CollSeq *pReq; - char colaff; + char aff; /* The collation sequence used by the comparison. If an index is to ** be used in place of a temp-table, it must be ordered according ** to this collation sequence. */ pReq = sqlite4BinaryCompareCollSeq(pParse, pX->pLeft, pRhs); - if( !pReq ) pReq = db->pDfltColl; /* Check that the affinity that will be used to perform the ** comparison is the same as the affinity of the column. If ** it is not, it is not possible to use any index. */ - colaff = (iCol<0) ? SQLITE4_AFF_NUMERIC : pTab->aCol[iCol].affinity; - if( 0==sqlite4IndexAffinityOk(pX, colaff) ) return 0; + aff = comparisonAffinity(pX); + if( aff!=SQLITE4_AFF_NONE && aff!=pTab->aCol[iCol].affinity ) return 0; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( (pIdx->aiColumn[0]==iCol) && sqlite4FindCollSeq(db, pIdx->azColl[0], 0)==pReq && (!bReqUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None)) @@ -1409,65 +1408,35 @@ return pIdx; } #endif /* SQLITE4_OMIT_SUBQUERY */ -#ifndef SQLITE4_OMIT_SUBQUERY /* ** This function is used by the implementation of the IN (...) operator. -** The pX parameter is the expression on the RHS of the IN operator, which -** might be either a list of expressions or a subquery. -** -** The job of this routine is to find or create a b-tree object that can -** be used either to test for membership in the RHS set or to iterate through -** all members of the RHS set, skipping duplicates. -** -** A cursor is opened on the b-tree object that the RHS of the IN operator -** and pX->iTable is set to the index of that cursor. -** +** It's job is to find or create a b-tree structure that may be used +** either to test for membership of the (...) set or to iterate through +** its members, skipping duplicates. +** +** The index of the cursor opened on the b-tree (database table, database index +** or ephermal table) is stored in pX->iTable before this function returns. ** The returned value of this function indicates the b-tree type, as follows: ** -** IN_INDEX_ROWID - The cursor was opened on the PK index of a -** table with an implicit integer primary key. -** IN_INDEX_INDEX_ASC - The cursor was opened on an ascending index. -** IN_INDEX_INDEX_DESC - The cursor was opened on a descending index. -** IN_INDEX_EPH - The cursor was opened on a specially created and -** populated epheremal table. +** IN_INDEX_ROWID - The cursor was opened on a database table. +** IN_INDEX_INDEX - The cursor was opened on a database index. +** IN_INDEX_EPH - The cursor was opened on a specially created and +** populated epheremal table. ** -** An existing b-tree might be used if the RHS expression pX is a simple -** subquery such as: +** An existing b-tree may only be used if the SELECT is of the simple +** form: ** ** SELECT FROM ** -** If the RHS of the IN operator is a list or a more complex subquery, then -** an ephemeral table might need to be generated from the RHS and then -** pX->iTable made to point to the ephermeral table instead of an -** existing table. -** -** -** ITERATING THROUGH SET MEMBERS -** -** If the prNotFound parameter is 0, then the b-tree will be used to -** iterate through the set members, skipping any duplicates. In this -** case the piCov parameter is always non-zero. An index on column -** of
is used in this case if: -** -** 1. The index guarantees the column is unique (i.e. it is a UNIQUE -** or PRIMARY KEY Index), and -** -** 2. The index uses the same collation sequence as the comparison -** performed by expression pX. -** -** 3. The index is a covering index for (either because it -** is a PRIMARY KEY or was created with a COVERING clause). -** -** Restriction (3) could be removed by the calling code in where.c. -** -** Before returning, *piCov is set to the column number of in -** the value associated with the selected covering or primary key index. -** -** SET MEMBERSHIP TESTS +** If the prNotFound parameter is 0, then the b-tree will be used to iterate +** through the set members, skipping any duplicates. In this case an +** epheremal table must be used unless the selected is guaranteed +** to be unique - either because it is an INTEGER PRIMARY KEY or it +** has a UNIQUE constraint or UNIQUE index. ** ** If the prNotFound parameter is not 0, then the b-tree will be used ** for fast set membership tests. In this case an epheremal table must ** be used unless is an INTEGER PRIMARY KEY or an index can ** be found with as its left-most column. @@ -1493,122 +1462,52 @@ ** } ** ** in order to avoid running the ** test more often than is necessary. */ -int sqlite4FindInIndex(Parse *pParse, Expr *pX, int *prNotFound, int *piCov){ - Select *p; /* SELECT to the right of IN operator */ +#ifndef SQLITE4_OMIT_SUBQUERY +int sqlite4FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ + Index *pIdx; int eType = 0; /* Type of RHS table. IN_INDEX_* */ int iTab = pParse->nTab++; /* Cursor of the RHS table */ - int mustBeUnique = (prNotFound==0); /* True if RHS must be unique */ Vdbe *v = sqlite4GetVdbe(pParse); /* Virtual machine being coded */ assert( pX->op==TK_IN ); - assert( mustBeUnique==(piCov!=0) ); - - /* This function is only called from two places. In both cases the vdbe - ** has already been allocated. So assume sqlite4GetVdbe() is always - ** successful here. */ - assert(v); + assert( prNotFound ); /* Check to see if an existing table or index can be used to - ** satisfy the query. This is preferable to generating a new - ** ephemeral table. - */ - p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0); - if( ALWAYS(pParse->nErr==0) && isCandidateForInOpt(p) ){ - sqlite4 *db = pParse->db; /* Database connection */ - Table *pTab; /* Table
. */ - Expr *pExpr; /* Expression */ - int iCol; /* Index of column */ - int iDb; /* Database idx for pTab */ - Index *pIdx; /* Used to iterate through indexes on pTab */ - CollSeq *pReq; /* Collation sequence for comparison */ - char affinity; /* Affinity of selected column */ - int affinity_ok; /* True if the affinity matches */ - - assert( p ); /* Because of isCandidateForInOpt(p) */ - assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */ - assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */ - assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */ - pTab = p->pSrc->a[0].pTab; - pExpr = p->pEList->a[0].pExpr; - iCol = pExpr->iColumn; - - /* Code an OP_VerifyCookie for
. */ - iDb = sqlite4SchemaToIndex(db, pTab->pSchema); - sqlite4CodeVerifySchema(pParse, iDb); - - /* The collation sequence used by the comparison. If an index is to - ** be used in place of a temp-table, it must be ordered according - ** to this collation sequence. */ - pReq = sqlite4BinaryCompareCollSeq(pParse, pX->pLeft, pExpr); - - /* Check that the affinity that will be used to perform the - ** comparison is the same as the affinity of the column. If - ** it is not, it is not possible to use any index. */ - affinity = (iCol<0?SQLITE4_AFF_NUMERIC:pTab->aCol[iCol].affinity); - affinity_ok = sqlite4IndexAffinityOk(pX, affinity); - - for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){ - if( (pIdx->aiColumn[0]==iCol) - && (iCol<0 || sqlite4FindCollSeq(db, pIdx->azColl[0], 0)==pReq) - && (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None)) - ){ - int iAddr; - - if( mustBeUnique ){ - if( pIdx->eIndexType!=SQLITE4_INDEX_PRIMARYKEY ){ - int i; - for(i=0; inCover; i++){ - if( pIdx->aiCover[i]==iCol ) break; - } - if( i==pIdx->nCover ) continue; - *piCov = i; - }else{ - *piCov = iCol; - } - } - - iAddr = sqlite4CodeOnce(pParse); - sqlite4OpenIndex(pParse, iTab, iDb, pIdx, OP_OpenRead); - assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 ); - if( iCol<0 ){ - eType = IN_INDEX_ROWID; - }else{ - eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0]; - } - - sqlite4VdbeJumpHere(v, iAddr); - if( prNotFound && !pTab->aCol[iCol].notNull ){ - *prNotFound = ++pParse->nMem; - sqlite4VdbeAddOp2(v, OP_Null, 0, *prNotFound); - } - } - } - } - - if( eType==0 ){ - /* Could not found an existing table or index to use as the RHS b-tree. - ** We will have to generate an ephemeral table to do the job. - */ - u32 savedNQueryLoop = pParse->nQueryLoop; + ** satisfy the query. This is preferable to generating a new + ** ephemeral table. */ + pIdx = sqlite4FindExistingInIndex(pParse, pX, 0); + if( pIdx ){ + int iAddr; + char *pKey; + int iDb; /* aDb[] Index of database containing pIdx */ + + iDb = sqlite4SchemaToIndex(pParse->db, pIdx->pSchema); + pKey = (char *)sqlite4IndexKeyinfo(pParse, pIdx); + iAddr = sqlite4CodeOnce(pParse); + sqlite4VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb); + sqlite4VdbeChangeP4(v, -1 , pKey, P4_KEYINFO_HANDOFF); + VdbeComment((v, "%s", pIdx->zName)); + sqlite4VdbeJumpHere(v, iAddr); + + *prNotFound = ++pParse->nMem; + sqlite4VdbeAddOp2(v, OP_Null, 0, *prNotFound); + pX->iTable = iTab; + }else{ + /* Could not find an existing table or index to use as the RHS b-tree. + ** We will have to generate an ephemeral table to do the job. */ + double savedNQueryLoop = pParse->nQueryLoop; int rMayHaveNull = 0; eType = IN_INDEX_EPH; - if( prNotFound ){ - *prNotFound = rMayHaveNull = ++pParse->nMem; - sqlite4VdbeAddOp2(v, OP_Null, 0, *prNotFound); - }else{ - testcase( pParse->nQueryLoop>0 ); - pParse->nQueryLoop = 0; - *piCov = 0; - } - sqlite4CodeSubselect(pParse, pX, rMayHaveNull); + *prNotFound = rMayHaveNull = ++pParse->nMem; + sqlite4VdbeAddOp2(v, OP_Null, 0, *prNotFound); + sqlite4CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID); pParse->nQueryLoop = savedNQueryLoop; - }else{ - pX->iTable = iTab; } + return eType; } #endif /* @@ -1646,11 +1545,12 @@ */ #ifndef SQLITE4_OMIT_SUBQUERY int sqlite4CodeSubselect( Parse *pParse, /* Parsing context */ Expr *pExpr, /* The IN, SELECT, or EXISTS operator */ - int rMayHaveNull /* Register that records whether NULLs exist in RHS */ + int rMayHaveNull, /* Register that records whether NULLs exist in RHS */ + int isRowid /* If true, LHS of IN operator is a rowid */ ){ int testAddr = -1; /* One-time test address */ int rReg = 0; /* Register storing resulting */ Vdbe *v = sqlite4GetVdbe(pParse); if( NEVER(v==0) ) return 0; @@ -1705,11 +1605,11 @@ ** if either column has NUMERIC or INTEGER affinity. If neither ** 'x' nor the SELECT... statement are columns, then numeric affinity ** is used. */ pExpr->iTable = pParse->nTab++; - addr = sqlite4VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, 1); + addr = sqlite4VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid); memset(&keyInfo, 0, sizeof(keyInfo)); keyInfo.nField = 1; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ /* Case 1: expr IN (SELECT ...) @@ -1718,10 +1618,11 @@ ** table allocated and opened above. */ SelectDest dest; ExprList *pEList; + assert( !isRowid ); sqlite4SelectDestInit(&dest, SRT_Set, pExpr->iTable); dest.affinity = (u8)affinity; assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); pExpr->x.pSelect->iLimit = 0; if( sqlite4Select(pParse, pExpr->x.pSelect, &dest) ){ @@ -1741,11 +1642,11 @@ ** a column, use numeric affinity. */ int i; ExprList *pList = pExpr->x.pList; ExprListItem *pItem; - int r1, r2, r3, r4; + int r1, r2, r3; if( !affinity ){ affinity = SQLITE4_AFF_NONE; } keyInfo.aColl[0] = sqlite4ExprCollSeq(pParse, pExpr->pLeft); @@ -1767,22 +1668,34 @@ sqlite4VdbeChangeToNoop(v, testAddr); testAddr = -1; } /* Evaluate the expression and insert it into the temp table */ - r3 = sqlite4ExprCodeTarget(pParse, pE2, r1); - r4 = sqlite4GetTempReg(pParse); - sqlite4VdbeAddOp2(v, OP_MakeKey, pExpr->iTable, r4); - sqlite4VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); - sqlite4ExprCacheAffinityChange(pParse, r3, 1); - sqlite4VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r4); - sqlite4ReleaseTempReg(pParse, r4); + if( isRowid && sqlite4ExprIsInteger(pE2, &iValToIns) ){ + sqlite4VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns); + }else{ + r3 = sqlite4ExprCodeTarget(pParse, pE2, r1); + if( isRowid ){ + sqlite4VdbeAddOp2(v, OP_MustBeInt, r3, + sqlite4VdbeCurrentAddr(v)+2); + sqlite4VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); + }else{ + int r4 = sqlite4GetTempReg(pParse); + sqlite4VdbeAddOp2(v, OP_MakeKey, pExpr->iTable, r4); + sqlite4VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); + sqlite4ExprCacheAffinityChange(pParse, r3, 1); + sqlite4VdbeAddOp3(v, OP_IdxInsert, pExpr->iTable, r2, r4); + sqlite4ReleaseTempReg(pParse, r4); + } + } } sqlite4ReleaseTempReg(pParse, r1); sqlite4ReleaseTempReg(pParse, r2); } - sqlite4VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO); + if( !isRowid ){ + sqlite4VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO); + } break; } case TK_EXISTS: case TK_SELECT: @@ -1868,11 +1781,11 @@ ** pExpr->iTable will contains the values that make up the RHS. */ v = pParse->pVdbe; assert( v!=0 ); /* OOM detected prior to this routine */ VdbeNoopComment((v, "begin IN expr")); - eType = sqlite4FindInIndex(pParse, pExpr, &rRhsHasNull, 0); + eType = sqlite4FindInIndex(pParse, pExpr, &rRhsHasNull); /* Figure out the affinity to use to create a key from the results ** of the expression. affinityStr stores a static string suitable for ** P4 of OP_MakeRecord. */ @@ -2176,14 +2089,10 @@ int iCol, /* Index of the column to extract */ int regOut /* Extract the valud into this register */ ){ if( iCol<0 ){ sqlite4VdbeAddOp2(v, OP_Rowid, iTabCur, regOut); - }else if( IsKvstore(pTab) ){ - int aOp[2] = { OP_RowKey, OP_RowData }; - assert( iCol==0 || iCol==1 ); - sqlite4VdbeAddOp2(v, aOp[iCol], iTabCur, regOut); }else{ int op = IsVirtual(pTab) ? OP_VColumn : OP_Column; sqlite4VdbeAddOp3(v, op, iTabCur, iCol, regOut); } if( iCol>=0 ){ @@ -2675,11 +2584,11 @@ #ifndef SQLITE4_OMIT_SUBQUERY case TK_EXISTS: case TK_SELECT: { testcase( op==TK_EXISTS ); testcase( op==TK_SELECT ); - inReg = sqlite4CodeSubselect(pParse, pExpr, 0); + inReg = sqlite4CodeSubselect(pParse, pExpr, 0, 0); break; } case TK_IN: { int destIfFalse = sqlite4VdbeMakeLabel(v); int destIfNull = sqlite4VdbeMakeLabel(v); Index: src/fkey.c ================================================================== --- src/fkey.c +++ src/fkey.c @@ -511,11 +511,11 @@ sqlite4ResolveExprNames(&sNameContext, pWhere); /* Create VDBE to loop through the entries in pSrc that match the WHERE ** clause. For each row found, increment the relevant constraint counter ** by nIncr. */ - pWInfo = sqlite4WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0); + pWInfo = sqlite4WhereBegin(pParse, pSrc, pWhere, 0, 0, 0); if( nIncr>0 && pFKey->isDeferred==0 ){ sqlite4ParseToplevel(pParse)->mayAbort = 1; } sqlite4VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); if( pWInfo ){ @@ -864,11 +864,11 @@ for(i=0; inCol; i++){ char *zKey = p->aCol[i].zCol; int iKey; for(iKey=0; iKeynCol; iKey++){ Column *pCol = &pTab->aCol[iKey]; - if( (zKey ? !sqlite4_stricmp(pCol->zName,zKey) : pCol->iPrimKey>0) ){ + if( (zKey ? !sqlite4_stricmp(pCol->zName, zKey) : pCol->isPrimKey) ){ if( aChange[iKey]>=0 ) return 1; } } } } Index: src/fts5.c ================================================================== --- src/fts5.c +++ src/fts5.c @@ -1388,11 +1388,11 @@ int nAlloc; /* If pnRow is not NULL, then this is the global record. Read the ** number of documents in the table from the start of the record. */ if( pnRow ){ - iOff += sqlite4GetVarint64(&aData[iOff], nData-iOff, (u64 *)pnRow); + iOff += sqlite4GetVarint(&aData[iOff], (u64 *)pnRow); } iOff += getVarint32(&aData[iOff], nStream); nAlloc = (nStream < nMinStream ? nMinStream : nStream); pSz = sqlite4DbMallocZero(db, @@ -1407,11 +1407,11 @@ pSz->nStream = nAlloc; while( iOffaSz[iCol*nAlloc]; for(i=0; i=0 ){ - iOff += sqlite4PutVarint64(&a[iOff], nRow); + iOff += sqlite4PutVarint(&a[iOff], nRow); } - iOff += sqlite4PutVarint64(&a[iOff], pSz->nStream); + iOff += sqlite4PutVarint(&a[iOff], pSz->nStream); for(iCol=0; iColnCol; iCol++){ int i; for(i=0; inStream; i++){ - iOff += sqlite4PutVarint64(&a[iOff], pSz->aSz[iCol*pSz->nStream+i]); + iOff += sqlite4PutVarint(&a[iOff], pSz->aSz[iCol*pSz->nStream+i]); } } return sqlite4KVStoreReplace(p, aKey, nKey, a, iOff); } @@ -2827,20 +2827,24 @@ rc = sqlite4KVCursorSeek(pCsr->pCsr, aKey, nKey, 0); if( rc==SQLITE4_NOTFOUND ){ rc = SQLITE4_CORRUPT_BKPT; } } + + if( rc==SQLITE4_OK ){ + rc = sqlite4KVCursorData(pCsr->pCsr, 0, -1, &aData, &nData); + } if( rc==SQLITE4_OK ){ int i; - RowDecoder *pCodec; /* The decoder object */ + ValueDecoder *pCodec; /* The decoder object */ - rc = sqlite4VdbeDecoderCreate(db,0, pCsr->pCsr, pInfo->nCol, &pCodec); + rc = sqlite4VdbeCreateDecoder(db, aData, nData, pInfo->nCol, &pCodec); for(i=0; rc==SQLITE4_OK && inCol; i++){ - rc = sqlite4VdbeDecoderGetColumn(pCodec, i, 0, &pCsr->aMem[i]); + rc = sqlite4VdbeDecodeValue(pCodec, i, 0, &pCsr->aMem[i]); } - sqlite4VdbeDecoderDestroy(pCodec); + sqlite4VdbeDestroyDecoder(pCodec); } if( rc==SQLITE4_OK ) pCsr->bMemValid = 1; } } Index: src/fts5func.c ================================================================== --- src/fts5func.c +++ src/fts5func.c @@ -18,11 +18,11 @@ ** Stephen Robertson and Hugo Zaragoza: "The Probablistic Relevance ** Framework: BM25 and Beyond", 2009. */ #include "sqliteInt.h" -#include // temporary: For log() */ +#include /* temporary: For log() */ static char fts5Tolower(char c){ if( c>='A' && c<='Z' ) c = c + ('a' - 'A'); return c; } Index: src/func.c ================================================================== --- src/func.c +++ src/func.c @@ -797,10 +797,17 @@ sqlite4_result_text(context, sqlite4_compileoption_get(n), -1, SQLITE4_STATIC, 0); } #endif /* SQLITE4_OMIT_COMPILEOPTION_DIAGS */ +/* Array for converting from half-bytes (nybbles) into ASCII hex +** digits. */ +static const char hexdigits[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' +}; + /* ** EXPERIMENTAL - This is not an official function. The interface may ** change. This function may disappear. Do not write code that depends ** on this function. ** @@ -820,18 +827,22 @@ break; } case SQLITE4_BLOB: { int nBlob; char *zText = 0; - const char *zBlob = sqlite4_value_blob(argv[0], &nBlob); + char const *zBlob = sqlite4_value_blob(argv[0], &nBlob); zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4); if( zText ){ + int i; + for(i=0; i>4)&0x0F]; + zText[(i*2)+3] = hexdigits[(zBlob[i])&0x0F]; + } + zText[(nBlob*2)+2] = '\''; + zText[(nBlob*2)+3] = '\0'; zText[0] = 'x'; zText[1] = '\''; - sqlite4BlobToHex(nBlob, (const u8*)zBlob, zText+2); - zText[(nBlob*2)+2] = '\''; - zText[(nBlob*2)+3] = 0; sqlite4_result_text(context, zText, -1, SQLITE4_TRANSIENT, 0); sqlite4_free(sqlite4_context_env(context), zText); } break; } @@ -875,17 +886,22 @@ int argc, sqlite4_value **argv ){ int i, n; const unsigned char *pBlob; - char *zHex; + char *zHex, *z; assert( argc==1 ); UNUSED_PARAMETER(argc); pBlob = sqlite4_value_blob(argv[0], &n); - zHex = contextMalloc(context, ((i64)n)*2 + 1); + z = zHex = contextMalloc(context, ((i64)n)*2 + 1); if( zHex ){ - sqlite4BlobToHex(n, (const u8*)pBlob, zHex); + for(i=0; i>4)&0xf]; + *(z++) = hexdigits[c&0xf]; + } + *z = 0; sqlite4_result_text(context, zHex, n*2, SQLITE4_DYNAMIC, 0); } } /* Index: src/insert.c ================================================================== --- src/insert.c +++ src/insert.c @@ -611,10 +611,27 @@ v = sqlite4GetVdbe(pParse); if( v==0 ) goto insert_cleanup; if( pParse->nested==0 ) sqlite4VdbeCountChanges(v); sqlite4BeginWriteOperation(pParse, pSelect || pTrigger, iDb); +#ifndef SQLITE4_OMIT_XFER_OPT + /* If the statement is of the form + ** + ** INSERT INTO SELECT * FROM ; + ** + ** Then special optimizations can be applied that make the transfer + ** very fast and which reduce fragmentation of indices. + ** + ** This is the 2nd template. + */ + if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){ + assert( !pTrigger ); + assert( pList==0 ); + goto insert_end; + } +#endif /* SQLITE4_OMIT_XFER_OPT */ + /* If this is an AUTOINCREMENT table, look up the sequence number in the ** sqlite_sequence table and store it in memory cell regAutoinc. */ regAutoinc = autoIncBegin(pParse, iDb, pTab); @@ -1408,11 +1425,10 @@ int i; Vdbe *v; Index *pIdx; u8 pik_flags; int regRec; - int regCover; v = sqlite4GetVdbe(pParse); assert( v!=0 ); assert( pTab->pSelect==0 ); /* This table is not a VIEW */ @@ -1420,22 +1436,16 @@ pik_flags = 0; }else{ pik_flags = OPFLAG_NCHANGE | (isUpdate?OPFLAG_ISUPDATE:0); } - /* Generate code to serialize array of registers into a database record. - ** This OP_MakeRecord also serves to apply affinities to the array of - ** input registers at regContent. For this reason it must be executed - ** before any MakeRecord instructions used to create covering index - ** records. */ + /* Generate code to serialize array of registers into a database record. */ regRec = sqlite4GetTempReg(pParse); sqlite4VdbeAddOp3(v, OP_MakeRecord, regContent, pTab->nCol, regRec); sqlite4TableAffinityStr(v, pTab); sqlite4ExprCacheAffinityChange(pParse, regContent, pTab->nCol); - regCover = sqlite4GetTempReg(pParse); - /* Write the entry to each index. */ for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ assert( pIdx->eIndexType!=SQLITE4_INDEX_PRIMARYKEY || aRegIdx[i] ); if( pIdx->eIndexType==SQLITE4_INDEX_FTS5 ){ int iPK; @@ -1446,25 +1456,12 @@ int regData = 0; int flags = 0; if( pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY ){ regData = regRec; flags = pik_flags; - }else if( pIdx->nCover>0 ){ - int nByte = sizeof(int)*pIdx->nCover; - int *aiPermute = (int *)sqlite4DbMallocRaw(pParse->db, nByte); - - if( aiPermute ){ - memcpy(aiPermute, pIdx->aiCover, nByte); - sqlite4VdbeAddOp4( - v, OP_Permutation, pIdx->nCover, 0, 0, - (char*)aiPermute, P4_INTARRAY - ); - } - regData = regCover; - sqlite4VdbeAddOp3(v, OP_MakeRecord, regContent, pIdx->nCover, regData); - } - sqlite4VdbeAddOp3(v, OP_Insert, baseCur+i, regData, aRegIdx[i]); + } + sqlite4VdbeAddOp3(v, OP_IdxInsert, baseCur+i, regData, aRegIdx[i]); sqlite4VdbeChangeP5(v, flags); } } } @@ -1524,5 +1521,325 @@ ** purposes only - to make sure the transfer optimization really ** is happening when it is suppose to. */ int sqlite4_xferopt_count; #endif /* SQLITE4_TEST */ + + +#ifndef SQLITE4_OMIT_XFER_OPT +/* +** Check to collation names to see if they are compatible. +*/ +static int xferCompatibleCollation(const char *z1, const char *z2){ + if( z1==0 ){ + return z2==0; + } + if( z2==0 ){ + return 0; + } + return sqlite4_stricmp(z1, z2)==0; +} + + +/* +** Check to see if index pSrc is compatible as a source of data +** for index pDest in an insert transfer optimization. The rules +** for a compatible index: +** +** * The index is over the same set of columns +** * The same DESC and ASC markings occurs on all columns +** * The same onError processing (OE_Abort, OE_Ignore, etc) +** * The same collating sequence on each column +*/ +static int xferCompatibleIndex(Index *pDest, Index *pSrc){ + int i; + assert( pDest && pSrc ); + assert( pDest->pTable!=pSrc->pTable ); + if( pDest->nColumn!=pSrc->nColumn ){ + return 0; /* Different number of columns */ + } + if( pDest->onError!=pSrc->onError ){ + return 0; /* Different conflict resolution strategies */ + } + for(i=0; inColumn; i++){ + if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){ + return 0; /* Different columns indexed */ + } + if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){ + return 0; /* Different sort orders */ + } + if( !xferCompatibleCollation(pSrc->azColl[i],pDest->azColl[i]) ){ + return 0; /* Different collating sequences */ + } + } + + /* If no test above fails then the indices must be compatible */ + return 1; +} + +/* +** Attempt the transfer optimization on INSERTs of the form +** +** INSERT INTO tab1 SELECT * FROM tab2; +** +** The xfer optimization transfers raw records from tab2 over to tab1. +** Columns are not decoded and reassemblied, which greatly improves +** performance. Raw index records are transferred in the same way. +** +** The xfer optimization is only attempted if tab1 and tab2 are compatible. +** There are lots of rules for determining compatibility - see comments +** embedded in the code for details. +** +** This routine returns TRUE if the optimization is guaranteed to be used. +** Sometimes the xfer optimization will only work if the destination table +** is empty - a factor that can only be determined at run-time. In that +** case, this routine generates code for the xfer optimization but also +** does a test to see if the destination table is empty and jumps over the +** xfer optimization code if the test fails. In that case, this routine +** returns FALSE so that the caller will know to go ahead and generate +** an unoptimized transfer. This routine also returns FALSE if there +** is no chance that the xfer optimization can be applied. +** +** This optimization is particularly useful at making VACUUM run faster. +*/ +static int xferOptimization( + Parse *pParse, /* Parser context */ + Table *pDest, /* The table we are inserting into */ + Select *pSelect, /* A SELECT statement to use as the data source */ + int onError, /* How to handle constraint errors */ + int iDbDest /* The database of pDest */ +){ + ExprList *pEList; /* The result set of the SELECT */ + Table *pSrc; /* The table in the FROM clause of SELECT */ + Index *pSrcIdx, *pDestIdx; /* Source and destination indices */ + struct SrcList_item *pItem; /* An element of pSelect->pSrc */ + int i; /* Loop counter */ + int iDbSrc; /* The database of pSrc */ + int iSrc, iDest; /* Cursors from source and destination */ + int addr1, addr2; /* Loop addresses */ + int emptyDestTest; /* Address of test for empty pDest */ + int emptySrcTest; /* Address of test for empty pSrc */ + Vdbe *v; /* The VDBE we are building */ + KeyInfo *pKey; /* Key information for an index */ + int regAutoinc; /* Memory register used by AUTOINC */ + int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */ + int regData, regRowid, regKey; /* Registers holding data and rowid */ + + if( pSelect==0 ){ + return 0; /* Must be of the form INSERT INTO ... SELECT ... */ + } + if( sqlite4TriggerList(pParse, pDest) ){ + return 0; /* tab1 must not have triggers */ + } +#ifndef SQLITE4_OMIT_VIRTUALTABLE + if( pDest->tabFlags & TF_Virtual ){ + return 0; /* tab1 must not be a virtual table */ + } +#endif + if( onError==OE_Default ){ + if( pDest->iPKey>=0 ) onError = pDest->keyConf; + if( onError==OE_Default ) onError = OE_Abort; + } + assert(pSelect->pSrc); /* allocated even if there is no FROM clause */ + if( pSelect->pSrc->nSrc!=1 ){ + return 0; /* FROM clause must have exactly one term */ + } + if( pSelect->pSrc->a[0].pSelect ){ + return 0; /* FROM clause cannot contain a subquery */ + } + if( pSelect->pWhere ){ + return 0; /* SELECT may not have a WHERE clause */ + } + if( pSelect->pOrderBy ){ + return 0; /* SELECT may not have an ORDER BY clause */ + } + /* Do not need to test for a HAVING clause. If HAVING is present but + ** there is no ORDER BY, we will get an error. */ + if( pSelect->pGroupBy ){ + return 0; /* SELECT may not have a GROUP BY clause */ + } + if( pSelect->pLimit ){ + return 0; /* SELECT may not have a LIMIT clause */ + } + assert( pSelect->pOffset==0 ); /* Must be so if pLimit==0 */ + if( pSelect->pPrior ){ + return 0; /* SELECT may not be a compound query */ + } + if( pSelect->selFlags & SF_Distinct ){ + return 0; /* SELECT may not be DISTINCT */ + } + pEList = pSelect->pEList; + assert( pEList!=0 ); + if( pEList->nExpr!=1 ){ + return 0; /* The result set must have exactly one column */ + } + assert( pEList->a[0].pExpr ); + if( pEList->a[0].pExpr->op!=TK_ALL ){ + return 0; /* The result set must be the special operator "*" */ + } + + /* At this point we have established that the statement is of the + ** correct syntactic form to participate in this optimization. Now + ** we have to check the semantics. + */ + pItem = pSelect->pSrc->a; + pSrc = sqlite4LocateTable(pParse, 0, pItem->zName, pItem->zDatabase); + if( pSrc==0 ){ + return 0; /* FROM clause does not contain a real table */ + } + if( pSrc==pDest ){ + return 0; /* tab1 and tab2 may not be the same table */ + } +#ifndef SQLITE4_OMIT_VIRTUALTABLE + if( pSrc->tabFlags & TF_Virtual ){ + return 0; /* tab2 must not be a virtual table */ + } +#endif + if( pSrc->pSelect ){ + return 0; /* tab2 may not be a view */ + } + if( pDest->nCol!=pSrc->nCol ){ + return 0; /* Number of columns must be the same in tab1 and tab2 */ + } + if( pDest->iPKey!=pSrc->iPKey ){ + return 0; /* Both tables must have the same INTEGER PRIMARY KEY */ + } + for(i=0; inCol; i++){ + if( pDest->aCol[i].affinity!=pSrc->aCol[i].affinity ){ + return 0; /* Affinity must be the same on all columns */ + } + if( !xferCompatibleCollation(pDest->aCol[i].zColl, pSrc->aCol[i].zColl) ){ + return 0; /* Collating sequence must be the same on all columns */ + } + if( pDest->aCol[i].notNull && !pSrc->aCol[i].notNull ){ + return 0; /* tab2 must be NOT NULL if tab1 is */ + } + } + for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ + if( pDestIdx->onError!=OE_None ){ + destHasUniqueIdx = 1; + } + for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ + if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; + } + if( pSrcIdx==0 ){ + return 0; /* pDestIdx has no corresponding index in pSrc */ + } + } +#ifndef SQLITE4_OMIT_CHECK + if( pDest->pCheck && sqlite4ExprCompare(pSrc->pCheck, pDest->pCheck) ){ + return 0; /* Tables have different CHECK constraints. Ticket #2252 */ + } +#endif +#ifndef SQLITE4_OMIT_FOREIGN_KEY + /* Disallow the transfer optimization if the destination table constains + ** any foreign key constraints. This is more restrictive than necessary. + ** But the main beneficiary of the transfer optimization is the VACUUM + ** command, and the VACUUM command disables foreign key constraints. So + ** the extra complication to make this rule less restrictive is probably + ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e] + */ + if( (pParse->db->flags & SQLITE4_ForeignKeys)!=0 && pDest->pFKey!=0 ){ + return 0; + } +#endif + + /* If we get this far, it means that the xfer optimization is at + ** least a possibility, though it might only work if the destination + ** table (tab1) is initially empty. + */ +#ifdef SQLITE4_TEST + sqlite4_xferopt_count++; +#endif + iDbSrc = sqlite4SchemaToIndex(pParse->db, pSrc->pSchema); + v = sqlite4GetVdbe(pParse); + sqlite4CodeVerifySchema(pParse, iDbSrc); + iSrc = pParse->nTab++; + iDest = pParse->nTab++; + regAutoinc = autoIncBegin(pParse, iDbDest, pDest); + sqlite4OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); + if( (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */ + || destHasUniqueIdx /* (2) */ + || (onError!=OE_Abort && onError!=OE_Rollback) /* (3) */ + ){ + /* In some circumstances, we are able to run the xfer optimization + ** only if the destination table is initially empty. This code makes + ** that determination. Conditions under which the destination must + ** be empty: + ** + ** (1) There is no INTEGER PRIMARY KEY but there are indices. + ** (If the destination is not initially empty, the rowid fields + ** of index entries might need to change.) + ** + ** (2) The destination has a unique index. (The xfer optimization + ** is unable to test uniqueness.) + ** + ** (3) onError is something other than OE_Abort and OE_Rollback. + */ + addr1 = sqlite4VdbeAddOp2(v, OP_Rewind, iDest, 0); + emptyDestTest = sqlite4VdbeAddOp2(v, OP_Goto, 0, 0); + sqlite4VdbeJumpHere(v, addr1); + }else{ + emptyDestTest = 0; + } + sqlite4OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); + emptySrcTest = sqlite4VdbeAddOp2(v, OP_Rewind, iSrc, 0); + regKey = sqlite4GetTempReg(pParse); + regData = sqlite4GetTempReg(pParse); + regRowid = sqlite4GetTempReg(pParse); + if( pDest->iPKey>=0 ){ + addr1 = sqlite4VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); + addr2 = sqlite4VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); + sqlite4HaltConstraint( + pParse, onError, "PRIMARY KEY must be unique", P4_STATIC); + sqlite4VdbeJumpHere(v, addr2); + autoIncStep(pParse, regAutoinc, regRowid); + }else if( pDest->pIndex==0 ){ + addr1 = sqlite4VdbeAddOp2(v, OP_NewRowid, iDest, regRowid); + }else{ + addr1 = sqlite4VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); + assert( (pDest->tabFlags & TF_Autoincrement)==0 ); + } + sqlite4VdbeAddOp2(v, OP_RowData, iSrc, regData); + sqlite4VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid); + sqlite4VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_APPEND); + sqlite4VdbeChangeP4(v, -1, pDest->zName, 0); + sqlite4VdbeAddOp2(v, OP_Next, iSrc, addr1); + for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ + for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){ + if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; + } + assert( pSrcIdx ); + sqlite4VdbeAddOp2(v, OP_Close, iSrc, 0); + sqlite4VdbeAddOp2(v, OP_Close, iDest, 0); + pKey = sqlite4IndexKeyinfo(pParse, pSrcIdx); + sqlite4VdbeAddOp4(v, OP_OpenRead, iSrc, pSrcIdx->tnum, iDbSrc, + (char*)pKey, P4_KEYINFO_HANDOFF); + VdbeComment((v, "%s", pSrcIdx->zName)); + pKey = sqlite4IndexKeyinfo(pParse, pDestIdx); + sqlite4VdbeAddOp4(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest, + (char*)pKey, P4_KEYINFO_HANDOFF); + VdbeComment((v, "%s", pDestIdx->zName)); + addr1 = sqlite4VdbeAddOp2(v, OP_Rewind, iSrc, 0); + sqlite4VdbeAddOp2(v, OP_RowKey, iSrc, regKey); + sqlite4VdbeAddOp2(v, OP_RowData, iSrc, regData); + sqlite4VdbeAddOp3(v, OP_IdxInsert, iDest, regKey, regData); + sqlite4VdbeChangeP5(v, OPFLAG_APPENDBIAS); + sqlite4VdbeAddOp2(v, OP_Next, iSrc, addr1+1); + sqlite4VdbeJumpHere(v, addr1); + } + sqlite4VdbeJumpHere(v, emptySrcTest); + sqlite4ReleaseTempReg(pParse, regRowid); + sqlite4ReleaseTempReg(pParse, regData); + sqlite4ReleaseTempReg(pParse, regKey); + sqlite4VdbeAddOp2(v, OP_Close, iSrc, 0); + sqlite4VdbeAddOp2(v, OP_Close, iDest, 0); + if( emptyDestTest ){ + sqlite4VdbeAddOp2(v, OP_Halt, SQLITE4_OK, 0); + sqlite4VdbeJumpHere(v, emptyDestTest); + sqlite4VdbeAddOp2(v, OP_Close, iDest, 0); + return 0; + }else{ + return 1; + } +} +#endif /* SQLITE4_OMIT_XFER_OPT */ Index: src/kv.c ================================================================== --- src/kv.c +++ src/kv.c @@ -376,11 +376,11 @@ /* ** Store schema cookie value iVal. */ int sqlite4KVStorePutSchema(KVStore *p, unsigned int iVal){ - kvTrace(p, "xPutMeta(%d,%d)", p->kvId, (int)iVal); + kvTrace(p, "xPutMeta(%d,%d) -> %s", p->kvId, (int)iVal); return p->pStoreVfunc->xPutMeta(p, iVal); } /* ** Read the schema cookie value into *piVal. Index: src/lsmInt.h ================================================================== --- src/lsmInt.h +++ src/lsmInt.h @@ -871,11 +871,10 @@ int lsmBeginReadTrans(lsm_db *); int lsmBeginWriteTrans(lsm_db *); int lsmBeginFlush(lsm_db *); int lsmDetectRoTrans(lsm_db *db, int *); -int lsmBeginRoTrans(lsm_db *db); int lsmBeginWork(lsm_db *); void lsmFinishWork(lsm_db *, int, int *); int lsmFinishRecovery(lsm_db *); Index: src/lsm_ckpt.c ================================================================== --- src/lsm_ckpt.c +++ src/lsm_ckpt.c @@ -1218,10 +1218,11 @@ /* ** Set the output variable to the number of KB of data written into the ** database file since the most recent checkpoint. */ int lsmCheckpointSize(lsm_db *db, int *pnKB){ + ShmHeader *pShm = db->pShmhdr; int rc = LSM_OK; u32 nSynced; /* Set nSynced to the number of pages that had been written when the ** database was last checkpointed. */ @@ -1233,5 +1234,6 @@ *pnKB = (int)(( ((i64)(nWrite - nSynced) * nPgsz) + 1023) / 1024); } return rc; } + Index: src/lsm_file.c ================================================================== --- src/lsm_file.c +++ src/lsm_file.c @@ -2383,10 +2383,11 @@ u8 *aBuf = 0; u8 *aData = 0; for(i=0; rc==LSM_OK && inMapLimit ){ u8 *aMap = (u8 *)(pFS->pMap); aData = &aMap[iOff]; Index: src/lsm_log.c ================================================================== --- src/lsm_log.c +++ src/lsm_log.c @@ -1130,5 +1130,7 @@ lsmFree(db->pEnv, db->pLogWriter->buf.z); lsmFree(db->pEnv, db->pLogWriter); db->pLogWriter = 0; } } + + Index: src/lsm_main.c ================================================================== --- src/lsm_main.c +++ src/lsm_main.c @@ -1005,5 +1005,7 @@ } } return rc; } + + Index: src/lsm_shared.c ================================================================== --- src/lsm_shared.c +++ src/lsm_shared.c @@ -956,11 +956,11 @@ (int)lsmCheckpointId(pDb->aSnapshot, 0) ); #endif } - if( rc==LSM_OK && bTruncate && nBlock>0 ){ + if( rc==LSM_OK && bTruncate ){ rc = lsmFsTruncateDb(pDb->pFS, (i64)nBlock*lsmFsBlockSize(pDb->pFS)); } } lsmShmLock(pDb, LSM_LOCK_CHECKPOINTER, LSM_LOCK_UNLOCK, 0); @@ -1963,5 +1963,6 @@ *pnKB = nKB; } return rc; } + Index: src/lsm_sorted.c ================================================================== --- src/lsm_sorted.c +++ src/lsm_sorted.c @@ -1974,11 +1974,15 @@ switch( iKey ){ case CURSOR_DATA_TREE0: case CURSOR_DATA_TREE1: { TreeCursor *pTreeCsr = pCsr->apTreeCsr[iKey-CURSOR_DATA_TREE0]; if( lsmTreeCursorValid(pTreeCsr) ){ + int nVal; + void *pVal; + lsmTreeCursorKey(pTreeCsr, &eType, &pKey, &nKey); + lsmTreeCursorValue(pTreeCsr, &pVal, &nVal); } break; } case CURSOR_DATA_SYSTEM: { @@ -2369,10 +2373,11 @@ } static int multiCursorAddAll(MultiCursor *pCsr, Snapshot *pSnap){ Level *pLvl; int nPtr = 0; + int iPtr = 0; int rc = LSM_OK; for(pLvl=pSnap->pLevel; pLvl; pLvl=pLvl->pNext){ /* If the LEVEL_INCOMPLETE flag is set, then this function is being ** called (indirectly) from within a sortedNewToplevel() call to @@ -2689,11 +2694,11 @@ multiCursorGetKey(pCsr, pCsr->aTree[1], &pCsr->eType, &pKey, &nKey); *pRc = sortedBlobSet(pCsr->pDb->pEnv, &pCsr->key, pKey, nKey); } } -#ifdef LSM_DEBUG_EXPENSIVE +#ifndef NDEBUG static void assertCursorTree(MultiCursor *pCsr){ int bRev = !!(pCsr->flags & CURSOR_PREV_OK); int *aSave = pCsr->aTree; int nSave = pCsr->nTree; int rc; @@ -3681,11 +3686,17 @@ MergeWorker *pMW, /* Merge worker object */ int iTopic, /* Topic value for this key */ void *pKey, /* Pointer to key buffer */ int nKey /* Size of pKey buffer in bytes */ ){ + lsm_db *pDb = pMW->pDb; /* Database handle */ int rc = LSM_OK; /* Return Code */ + int iLevel; /* Level of b-tree hierachy to write to */ + int nData; /* Size of aData[] in bytes */ + u8 *aData; /* Page data for level iLevel */ + int iOff; /* Offset on b-tree page to write record to */ + int nRec; /* Initial number of records on b-tree page */ Pgno iPtr; /* Pointer value to accompany pKey/nKey */ assert( pMW->aSave[0].bStore==0 ); assert( pMW->aSave[1].bStore==0 ); rc = mergeWorkerBtreeIndirect(pMW); @@ -3814,10 +3825,11 @@ Pgno iFPtr /* Pointer value for footer of new page */ ){ int rc = LSM_OK; /* Return code */ Page *pNext = 0; /* New page appended to run */ lsm_db *pDb = pMW->pDb; /* Database handle */ + Segment *pSeg; /* Run to append to */ rc = lsmFsSortedAppend(pDb->pFS, pDb->pWorker, pMW->pLevel, 0, &pNext); assert( rc || pMW->pLevel->lhs.iFirst>0 || pMW->pDb->compress.xCompress ); if( rc==LSM_OK ){ @@ -4044,10 +4056,11 @@ */ static void mergeWorkerShutdown(MergeWorker *pMW, int *pRc){ int i; /* Iterator variable */ int rc = *pRc; MultiCursor *pCsr = pMW->pCsr; + Hierarchy *p = &pMW->hier; /* Unless the merge has finished, save the cursor position in the ** Merge.aInput[] array. See function mergeWorkerInit() for the ** code to restore a cursor position based on aInput[]. */ if( rc==LSM_OK && pCsr && lsmMCursorValid(pCsr) ){ @@ -4179,18 +4192,25 @@ lsm_db *pDb = pMW->pDb; /* Database handle */ MultiCursor *pCsr; /* Cursor to read input data from */ int rc = LSM_OK; /* Return code */ int eType; /* SORTED_SEPARATOR, WRITE or DELETE */ void *pKey; int nKey; /* Key */ + Segment *pSeg; /* Output segment */ Pgno iPtr; int iVal; pCsr = pMW->pCsr; + pSeg = &pMW->pLevel->lhs; /* Pull the next record out of the source cursor. */ lsmMCursorKey(pCsr, &pKey, &nKey); eType = pCsr->eType; + + if( eType & LSM_SYSTEMKEY ){ + int i; + i = 1; + } /* Figure out if the output record may have a different pointer value ** than the previous. This is the case if the current key is identical to ** a key that appears in the lowest level run being merged. If so, set ** iPtr to the absolute pointer value. If not, leave iPtr set to zero, Index: src/lsm_tree.c ================================================================== --- src/lsm_tree.c +++ src/lsm_tree.c @@ -102,13 +102,13 @@ #ifndef NDEBUG /* ** assert() that a TreeKey.flags value is sane. Usage: ** -** assert( lsmAssertFlagsOk(pTreeKey->flags) ); +** assert( assertFlagsOk(pTreeKey->flags) ); */ -static int lsmAssertFlagsOk(u8 keyflags){ +static int assertFlagsOk(u8 keyflags){ /* At least one flag must be set. Otherwise, what is this key doing? */ assert( keyflags!=0 ); /* The POINT_DELETE and INSERT flags cannot both be set. */ assert( (keyflags & LSM_POINT_DELETE)==0 || (keyflags & LSM_INSERT)==0 ); @@ -125,11 +125,11 @@ } static int assert_delete_ranges_match(lsm_db *); static int treeCountEntries(lsm_db *db); #else -# define lsmAssertFlagsOk(x) +# define assertFlagsOk(x) #endif /* ** Container for a key-value pair. Within the *-shm file, each key/value ** pair is stored in a single allocation (which may not actually be @@ -328,10 +328,11 @@ TreeNode *pNode, TreeNode *pParent, int iCell ){ TreeNode *p; + int rc = LSM_OK; u32 iPtr = getChildPtr(pParent, WORKING_VERSION, iCell); p = treeShmptr(db, iPtr); assert( p==pNode ); } #else @@ -577,11 +578,11 @@ TreeKey *pRet; lsm_db *pDb = pCsr->pDb; u32 iPtr = pCsr->apTreeNode[pCsr->iNode]->aiKeyPtr[pCsr->aiCell[pCsr->iNode]]; assert( iPtr ); - pRet = (TreeKey*)treeShmptrUnsafe(pDb, iPtr); + pRet = treeShmptrUnsafe(pDb, iPtr); if( !(pRet->flags & LSM_CONTIGUOUS) ){ pRet = treeShmkey(pDb, iPtr, TKV_LOADVAL, pBlob, pRc); } return pRet; @@ -1186,13 +1187,15 @@ ** code (i.e. LSM_IOERR or LSM_NOMEM) may be returned. */ static int treeCheckLinkedList(lsm_db *db){ int rc = LSM_OK; int nVisit = 0; + u32 iShmid; ShmChunk *p; p = treeShmChunkRc(db, db->treehdr.iFirst, &rc); + iShmid = p->iShmid; while( rc==LSM_OK && p ){ if( p->iNext ){ if( p->iNext>=db->treehdr.nChunk ){ rc = LSM_CORRUPT_BKPT; }else{ @@ -1393,10 +1396,11 @@ } } } static int treeNextIsEndDelete(lsm_db *db, TreeCursor *pCsr){ + TreeNode *pNode; int iNode = pCsr->iNode; int iCell = pCsr->aiCell[iNode]+1; /* Cursor currently points to a leaf node. */ assert( pCsr->iNode==(db->treehdr.root.nHeight-1) ); @@ -1415,10 +1419,11 @@ return 0; } static int treePrevIsStartDelete(lsm_db *db, TreeCursor *pCsr){ + TreeNode *pNode; int iNode = pCsr->iNode; /* Cursor currently points to a leaf node. */ assert( pCsr->iNode==(db->treehdr.root.nHeight-1) ); @@ -2003,11 +2008,11 @@ pCsr->apTreeNode[iNode] = pNode; /* Compare (pKey/nKey) with the key in the middle slot of B-tree node ** pNode. The middle slot is never empty. If the comparison is a match, ** then the search is finished. Break out of the loop. */ - pTreeKey = (TreeKey*)treeShmptrUnsafe(pDb, pNode->aiKeyPtr[1]); + pTreeKey = treeShmptrUnsafe(pDb, pNode->aiKeyPtr[1]); if( !(pTreeKey->flags & LSM_CONTIGUOUS) ){ pTreeKey = treeShmkey(pDb, pNode->aiKeyPtr[1], TKV_LOADKEY, &b, &rc); if( rc!=LSM_OK ) break; } res = treeKeycmp((void *)&pTreeKey[1], pTreeKey->nKey, pKey, nKey); @@ -2020,11 +2025,11 @@ ** to either the left or right key of the B-tree node, if such a key ** exists. */ iTest = (res>0 ? 0 : 2); iTreeKey = pNode->aiKeyPtr[iTest]; if( iTreeKey ){ - pTreeKey = (TreeKey*)treeShmptrUnsafe(pDb, iTreeKey); + pTreeKey = treeShmptrUnsafe(pDb, iTreeKey); if( !(pTreeKey->flags & LSM_CONTIGUOUS) ){ pTreeKey = treeShmkey(pDb, iTreeKey, TKV_LOADKEY, &b, &rc); if( rc ) break; } res = treeKeycmp((void *)&pTreeKey[1], pTreeKey->nKey, pKey, nKey); Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -695,10 +695,11 @@ sqlite4 *db, void *pArg, void (*xProfile)(void*,const char*,sqlite4_uint64), void (*xDestroy)(void*) ){ + void *pOld; sqlite4_mutex_enter(db->mutex); if( db->xProfileDestroy ){ db->xProfileDestroy(db->pProfileArg); } db->xProfile = xProfile; @@ -705,10 +706,44 @@ db->xProfileDestroy = xDestroy; db->pProfileArg = pArg; sqlite4_mutex_leave(db->mutex); } #endif /* SQLITE4_OMIT_TRACE */ + +/* +** This function returns true if main-memory should be used instead of +** a temporary file for transient pager files and statement journals. +** The value returned depends on the value of db->temp_store (runtime +** parameter) and the compile time value of SQLITE4_TEMP_STORE. The +** following table describes the relationship between these two values +** and this functions return value. +** +** SQLITE4_TEMP_STORE db->temp_store Location of temporary database +** ----------------- -------------- ------------------------------ +** 0 any file (return 0) +** 1 1 file (return 0) +** 1 2 memory (return 1) +** 1 0 file (return 0) +** 2 1 file (return 0) +** 2 2 memory (return 1) +** 2 0 memory (return 1) +** 3 any memory (return 1) +*/ +int sqlite4TempInMemory(const sqlite4 *db){ +#if SQLITE4_TEMP_STORE==1 + return ( db->temp_store==2 ); +#endif +#if SQLITE4_TEMP_STORE==2 + return ( db->temp_store!=1 ); +#endif +#if SQLITE4_TEMP_STORE==3 + return 1; +#endif +#if SQLITE4_TEMP_STORE<1 || SQLITE4_TEMP_STORE>3 + return 0; +#endif +} /* ** Return UTF-8 encoded English language explanation of the most recent ** error. */ Index: src/math.c ================================================================== --- src/math.c +++ src/math.c @@ -141,17 +141,16 @@ /* ** Multiply two numbers and return the result. */ sqlite4_num sqlite4_num_mul(sqlite4_num A, sqlite4_num B){ sqlite4_num r; - - if( A.e>SQLITE4_MX_EXP || B.e>SQLITE4_MX_EXP ){ - r.sign = A.sign ^ B.sign; - r.m = (A.m && B.m) ? 1 : 0; - r.e = SQLITE4_MX_EXP+1; - r.approx = 0; - return r; + if( A.e>SQLITE4_MX_EXP ){ + A.sign ^= B.sign; + return A; + }else if( B.e>SQLITE4_MX_EXP ){ + B.sign ^= A.sign; + return B; } if( A.m==0 ) return A; if( B.m==0 ) return B; while( A.m%10==0 ){ A.m /= 10; A.e++; } while( B.m%10==0 ){ B.m /= 10; B.e++; } @@ -192,11 +191,11 @@ return B; } if( B.m==0 ){ r.sign = A.sign ^ B.sign; r.e = SQLITE4_NAN_EXP; - r.m = 0; + r.m = 1; r.approx = 1; return r; } if( A.m==0 ){ return A; @@ -351,11 +350,11 @@ } /* If the IGNORE_WHITESPACE flag is set, ignore any leading whitespace. */ i = 0; if( flags & SQLITE4_IGNORE_WHITESPACE ){ - while( i=0 && x.e+n<=25 ){ @@ -722,9 +717,10 @@ *z++ = '-'; x.e = -x.e; }else{ *z++ = '+'; } + z++; zNum = renderInt(x.e&0x7fff, zBuf, sizeof(zBuf)); while( (z[0] = zNum[0])!=0 ){ z++; zNum++; } return (z-zOut); } Index: src/mem.c ================================================================== --- src/mem.c +++ src/mem.c @@ -778,5 +778,7 @@ void sqlite4_buffer_clear(sqlite4_buffer *pBuf){ sqlite4_mm_free(pBuf->pMM, pBuf->p); sqlite4_buffer_init(pBuf, pBuf->pMM); } + + Index: src/mutex_noop.c ================================================================== --- src/mutex_noop.c +++ src/mutex_noop.c @@ -106,12 +106,11 @@ /* ** The sqlite4_mutex_alloc() routine allocates a new ** mutex and returns a pointer to it. If it returns NULL ** that means that a mutex could not be allocated. */ -static sqlite4_mutex *debugMutexAlloc(void *pX, int id){ - sqlite4_env *pEnv = (sqlite4_env*)pX; +static sqlite4_mutex *debugMutexAlloc(sqlite4_env *pEnv, int id){ sqlite4DebugMutex *pNew = 0; pNew = sqlite4Malloc(pEnv, sizeof(*pNew)); if( pNew ){ pNew->id = id; pNew->cnt = 0; Index: src/parse.y ================================================================== --- src/parse.y +++ src/parse.y @@ -100,15 +100,10 @@ struct ValueList { ExprList *pList; Select *pSelect; }; -/* -** A COVERING clause. -*/ -struct CoveringOpt { IdList *pList; Token sEnd; }; - } // end %include // Input is a single SQL command input ::= cmdlist. cmdlist ::= cmdlist ecmd. @@ -303,11 +298,11 @@ // ccons ::= NULL onconf. ccons ::= NOT NULL onconf(R). {sqlite4AddNotNull(pParse, R);} ccons ::= PRIMARY KEY sortorder(Z) onconf(R) autoinc(I). {sqlite4AddPrimaryKey(pParse,0,R,I,Z);} -ccons ::= UNIQUE onconf(R). {sqlite4CreateIndex(pParse,0,0,0,R,0,0,0);} +ccons ::= UNIQUE onconf(R). {sqlite4CreateIndex(pParse,0,0,0,0,R,0,0,0,0,0);} ccons ::= CHECK LP expr(X) RP. {sqlite4AddCheckConstraint(pParse,X.pExpr);} ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R). {sqlite4CreateForeignKey(pParse,0,&T,TA,R);} ccons ::= defer_subclause(D). {sqlite4DeferForeignKey(pParse,D);} ccons ::= COLLATE ids(C). {sqlite4AddCollateType(pParse, &C);} @@ -354,11 +349,11 @@ conslist ::= tcons. tcons ::= CONSTRAINT nm. tcons ::= PRIMARY KEY LP idxlist(X) autoinc(I) RP onconf(R). {sqlite4AddPrimaryKey(pParse,X,R,I,0);} tcons ::= UNIQUE LP idxlist(X) RP onconf(R). - {sqlite4CreateIndex(pParse,0,X,0,R,0,0,0);} + {sqlite4CreateIndex(pParse,0,0,0,X,R,0,0,0,0,0);} tcons ::= CHECK LP expr(E) RP onconf. {sqlite4AddCheckConstraint(pParse,E.pExpr);} tcons ::= FOREIGN KEY LP idxlist(FA) RP REFERENCES nm(T) idxlist_opt(TA) refargs(R) defer_subclause_opt(D). { sqlite4CreateForeignKey(pParse, FA, &T, TA, R); @@ -1141,13 +1136,13 @@ C.tName1 = X; C.tName2 = D; C.pTblName = sqlite4SrcListAppend(pParse->db, 0, &Y, 0); } -cmd ::= createindex(C) LP idxlist(Z) RP(E) covering_opt(F). { - Token *pEnd = (F.pList ? &F.sEnd : &E); - sqlite4CreateIndex(pParse, &C, Z, F.pList, C.bUnique, pEnd, SQLITE4_SO_ASC,0); +cmd ::= createindex(C) LP idxlist(Z) RP(E). { + sqlite4CreateIndex(pParse, &C.tName1, &C.tName2, C.pTblName, Z, + C.bUnique, &C.tCreate, &E, SQLITE4_SO_ASC, C.bIfnotexist, 0); } %type uniqueflag {int} uniqueflag(A) ::= UNIQUE. {A = OE_Abort;} uniqueflag(A) ::= . {A = OE_None;} @@ -1211,22 +1206,10 @@ } uidxlist(A) ::= ids(Y). { A = sqlite4ExprListAppend(pParse, 0, sqlite4PExpr(pParse, @Y, 0, 0, &Y)); } -%type covering_opt { struct CoveringOpt } -%destructor covering_opt {sqlite4IdListDelete(pParse->db, $$.pList);} -covering_opt(A) ::= . { A.pList = 0; } -covering_opt(A) ::= COVERING ALL(X). { - A.pList = sqlite4DbMallocZero(pParse->db, sizeof(IdList)); - A.sEnd = X; -} -covering_opt(A) ::= COVERING LP inscollist(X) RP(Y). { - A.pList = X; - A.sEnd = Y; -} - ///////////////////////////// The DROP INDEX command ///////////////////////// // cmd ::= DROP INDEX ifexists(E) fullname(X). {sqlite4DropIndex(pParse, X, E);} Index: src/pragma.c ================================================================== --- src/pragma.c +++ src/pragma.c @@ -240,10 +240,11 @@ } } pParse->nMem = 2; sqlite4VdbeRunOnlyOnce(v); + if( pList && pList->nExpr>1 ) goto pragma_out; zRight = 0; if( pList ){ zRight = pList->a[0].zSpan; if( zRight==0 ){ assert( pList->a[0].pExpr->op==TK_ID ); @@ -370,11 +371,11 @@ if( pCol->zDflt ){ sqlite4VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0); }else{ sqlite4VdbeAddOp2(v, OP_Null, 0, 5); } - sqlite4VdbeAddOp2(v, OP_Integer, pCol->iPrimKey, 6); + sqlite4VdbeAddOp2(v, OP_Integer, pCol->isPrimKey, 6); sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 6); } } }else @@ -430,20 +431,23 @@ }else if( sqlite4_stricmp(zPragma, "database_list")==0 ){ int i; if( sqlite4ReadSchema(pParse) ) goto pragma_out; - sqlite4VdbeSetNumCols(v, 2); + sqlite4VdbeSetNumCols(v, 3); pParse->nMem = 3; sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE4_STATIC); sqlite4VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 2, COLNAME_NAME, "file", SQLITE4_STATIC); for(i=0; inDb; i++){ if( db->aDb[i].pKV==0 ) continue; assert( db->aDb[i].zName!=0 ); sqlite4VdbeAddOp2(v, OP_Integer, i, 1); sqlite4VdbeAddOp4(v, OP_String8, 0, 2, 0, db->aDb[i].zName, 0); - sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 2); + sqlite4VdbeAddOp4(v, OP_String8, 0, 3, 0, + "filename", 0); + sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 3); } }else if( sqlite4_stricmp(zPragma, "collation_list")==0 ){ int i = 0; @@ -634,41 +638,11 @@ ** Print an ascii rendering of the complete content of the database file. */ if( sqlite4_stricmp(zPragma, "kvdump")==0 ){ sqlite4KVStoreDump(db->aDb[0].pKV); }else - - /* - ** PRAGMA kvreplace(BLOB,BLOB) - ** - ** Insert or replace a single raw record into the KV store. This pragma - ** is exceedingly dangerous and should not be used by general-purpose - ** applications. It is intended for internal testing only - to provide - ** a convenient way to insert arbitrary content into the key/value store. - */ - if( sqlite4_stricmp(zPragma, "kvreplace")==0 - && pList->nExpr==2 - ){ - int r1, r2; - Vdbe *v = sqlite4GetVdbe(pParse); - pParse->nTab = 1; - pParse->nMem = 3; - sqlite4BeginWriteOperation(pParse, 0, iDb); - r1 = sqlite4ExprCodeTarget(pParse, pList->a[0].pExpr, 1); - sqlite4VdbeAddOp4(v, OP_HaltIfNull, SQLITE4_CONSTRAINT, OE_Abort, - r1, "key may not be null", P4_STATIC); - sqlite4VdbeAddOp1(v, OP_ToBlob, r1); - r2 = sqlite4ExprCodeTarget(pParse, pList->a[1].pExpr, 2); - sqlite4VdbeAddOp4(v, OP_HaltIfNull, SQLITE4_CONSTRAINT, OE_Abort, - r2, "value may not be null", P4_STATIC); - sqlite4VdbeAddOp1(v, OP_ToBlob, r2); - sqlite4VdbeAddOp0(v, OP_OpenWrite); - sqlite4VdbeAddOp3(v, OP_Insert, 0, r2, r1); - sqlite4VdbeAddOp0(v, OP_Halt); - }else -#endif /* SQLITE4_DEBUG - +#endif /* SQLITE4_OMIT_COMPILEOPTION_DIAGS */ /* ** PRAGMA integrity_check ** ** Check that for each table, the content of any auxilliary indexes are ** consistent with the primary key index. @@ -715,12 +689,12 @@ int nIdx = 0; int iPkCsr; Index *pPk; int iCsr; - /* Do nothing for views or sqlite_kvstore */ - if( IsView(pTab) || IsKvstore(pTab) ) continue; + /* Do nothing for views */ + if( IsView(pTab) ) continue; /* Open all indexes for table pTab. */ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY ){ pPk = pIdx; @@ -837,40 +811,10 @@ */ if( sqlite4_stricmp(zPragma, "shrink_memory")==0 ){ sqlite4_db_release_memory(db); }else - /* - ** PRAGMA schema_version - */ - if( sqlite4_stricmp(zPragma, "schema_version")==0 ){ - if( zRight ){ - /* Write the specified cookie value */ - static const VdbeOpList setCookie[] = { - { OP_Transaction, 0, 1, 0}, /* 0 */ - { OP_Integer, 0, 1, 0}, /* 1 */ - { OP_SetCookie, 0, 0, 1}, /* 2 */ - }; - int addr = sqlite4VdbeAddOpList(v, ArraySize(setCookie), setCookie); - sqlite4VdbeChangeP1(v, addr, iDb); - sqlite4VdbeChangeP1(v, addr+1, sqlite4Atoi(zRight)); - sqlite4VdbeChangeP1(v, addr+2, iDb); - }else{ - /* Read the specified cookie value */ - static const VdbeOpList readCookie[] = { - { OP_Transaction, 0, 0, 0}, /* 0 */ - { OP_ReadCookie, 0, 1, 0}, /* 1 */ - { OP_ResultRow, 1, 1, 0} - }; - int addr = sqlite4VdbeAddOpList(v, ArraySize(readCookie), readCookie); - sqlite4VdbeChangeP1(v, addr, iDb); - sqlite4VdbeChangeP1(v, addr+1, iDb); - sqlite4VdbeSetNumCols(v, 1); - sqlite4VdbeSetColName(v, 0, COLNAME_NAME, zPragma, SQLITE4_TRANSIENT); - } - }else - {/* Empty ELSE clause */} @@ -878,6 +822,635 @@ sqlite4DbFree(db, zPragma); /* sqlite4DbFree(db, zRight); */ sqlite4ExprListDelete(db, pList); } +#if 0 +/* +** Process a pragma statement. +** +** Pragmas are of this form: +** +** PRAGMA [database.]id [= value] +** +** The identifier might also be a string. The value is a string, and +** identifier, or a number. If minusFlag is true, then the value is +** a number that was preceded by a minus sign. +** +** If the left side is "database.id" then pId1 is the database name +** and pId2 is the id. If the left side is just "id" then pId1 is the +** id and pId2 is any empty string. +*/ +void sqlite4Pragma( + Parse *pParse, + Token *pId1, /* First part of [database.]id field */ + Token *pId2, /* Second part of [database.]id field, or NULL */ + ExprList *pList /* List of pragma arguments */ +){ + char *zLeft = 0; /* Nul-terminated UTF-8 string */ + char *zRight = 0; /* Nul-terminated UTF-8 string , or NULL */ + const char *zDb = 0; /* The database name */ + Token *pId; /* Pointer to token */ + int iDb; /* Database index for */ + sqlite4 *db = pParse->db; + Db *pDb; + Vdbe *v = pParse->pVdbe = sqlite4VdbeCreate(db); + if( v==0 ) return; + sqlite4VdbeRunOnlyOnce(v); + pParse->nMem = 2; + + /* Interpret the [database.] part of the pragma statement. iDb is the + ** index of the database this pragma is being applied to in db.aDb[]. */ + iDb = sqlite4TwoPartName(pParse, pId1, pId2, &pId); + if( iDb<0 ) return; + pDb = &db->aDb[iDb]; + + /* If the temp database has been explicitly named as part of the + ** pragma, make sure it is open. + */ + if( iDb==1 && sqlite4OpenTempDatabase(pParse) ){ + return; + } + + zLeft = sqlite4NameFromToken(db, pId); + if( !zLeft ) return; + if( minusFlag ){ + zRight = sqlite4MPrintf(db, "-%T", pValue); + }else{ + zRight = sqlite4NameFromToken(db, pValue); + } + + assert( pId2 ); + zDb = pId2->n>0 ? pDb->zName : 0; + if( sqlite4AuthCheck(pParse, SQLITE4_PRAGMA, zLeft, zRight, zDb) ){ + goto pragma_out; + } + + + +#ifndef SQLITE4_OMIT_FLAG_PRAGMAS + if( flagPragma(pParse, zLeft, zRight) ){ + /* The flagPragma() subroutine also generates any necessary code + ** there is nothing more to do here */ + }else +#endif /* SQLITE4_OMIT_FLAG_PRAGMAS */ + + /* + ** PRAGMA fts_check() + */ + if( sqlite4_stricmp(zLeft, "fts_check")==0 && zRight ){ + int iCksum1; + int iCksum2; + Index *pIdx; + Table *pTab; + Vdbe *v = sqlite4GetVdbe(pParse); + if( v==0 || sqlite4ReadSchema(pParse) ) goto pragma_out; + + iCksum1 = ++pParse->nMem; + iCksum2 = ++pParse->nMem; + sqlite4VdbeAddOp2(v, OP_Integer, 0, iCksum1); + sqlite4VdbeAddOp2(v, OP_Integer, 0, iCksum2); + + pIdx = sqlite4FindIndex(db, zRight, zDb); + if( pIdx && pIdx->eIndexType==SQLITE4_INDEX_FTS5 ){ + int iTab = pParse->nTab++; + int iAddr; + int iReg; + int i; + + pTab = pIdx->pTable; + sqlite4OpenPrimaryKey(pParse, iTab, iDb, pTab, OP_OpenRead); + iAddr = sqlite4VdbeAddOp2(v, OP_Rewind, iTab, 0); + + iReg = pParse->nMem+1; + pParse->nMem += (1 + pTab->nCol); + + sqlite4VdbeAddOp2(v, OP_RowKey, iTab, iReg); + for(i=0; inCol; i++){ + sqlite4VdbeAddOp3(v, OP_Column, iTab, i, iReg+1+i); + } + sqlite4Fts5CodeCksum(pParse, pIdx, iCksum1, iReg, 0); + + sqlite4VdbeAddOp2(v, OP_Next, iTab, iAddr+1); + sqlite4VdbeJumpHere(v, iAddr); + sqlite4VdbeAddOp1(v, OP_Close, iTab); + + sqlite4VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb); + iAddr = sqlite4VdbeAddOp2(v, OP_Rewind, iTab, 0); + + iReg = pParse->nMem+1; + pParse->nMem += 2; + sqlite4VdbeAddOp2(v, OP_RowKey, iTab, iReg); + sqlite4VdbeAddOp2(v, OP_RowData, iTab, iReg+1); + sqlite4Fts5CodeCksum(pParse, pIdx, iCksum2, iReg, 1); + + sqlite4VdbeAddOp2(v, OP_Next, iTab, iAddr+1); + sqlite4VdbeJumpHere(v, iAddr); + sqlite4VdbeAddOp1(v, OP_Close, iTab); + + iReg = ++pParse->nMem; + sqlite4VdbeAddOp4(v, OP_String8, 0, iReg, 0, "ok", 0); + iAddr = sqlite4VdbeAddOp3(v, OP_Eq, iCksum1, 0, iCksum2); + sqlite4VdbeAddOp4(v, OP_String8, 0, iReg, 0, "error - cksum mismatch", 0); + sqlite4VdbeJumpHere(v, iAddr); + sqlite4VdbeAddOp2(v, OP_ResultRow, iReg, 1); + + sqlite4VdbeSetNumCols(v, 1); + } + } + + + +#ifndef SQLITE4_OMIT_SCHEMA_PRAGMAS + /* + ** PRAGMA table_info(
) + ** + ** Return a single row for each column of the named table. The columns of + ** the returned data set are: + ** + ** cid: Column id (numbered from left to right, starting at 0) + ** name: Column name + ** type: Column declaration type. + ** notnull: True if 'NOT NULL' is part of column declaration + ** dflt_value: The default value for the column, if any. + */ + if( sqlite4_stricmp(zLeft, "table_info")==0 && zRight ){ + Table *pTab; + if( sqlite4ReadSchema(pParse) ) goto pragma_out; + pTab = sqlite4FindTable(db, zRight, zDb); + if( pTab ){ + int i; + int nHidden = 0; + Column *pCol; + sqlite4VdbeSetNumCols(v, 6); + pParse->nMem = 6; + sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 3, COLNAME_NAME, "notnull", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 4, COLNAME_NAME, "dflt_value", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 5, COLNAME_NAME, "pk", SQLITE4_STATIC); + sqlite4ViewGetColumnNames(pParse, pTab); + for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ + if( IsHiddenColumn(pCol) ){ + nHidden++; + continue; + } + sqlite4VdbeAddOp2(v, OP_Integer, i-nHidden, 1); + sqlite4VdbeAddOp4(v, OP_String8, 0, 2, 0, pCol->zName, 0); + sqlite4VdbeAddOp4(v, OP_String8, 0, 3, 0, + pCol->zType ? pCol->zType : "", 0); + sqlite4VdbeAddOp2(v, OP_Integer, (pCol->notNull ? 1 : 0), 4); + if( pCol->zDflt ){ + sqlite4VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0); + }else{ + sqlite4VdbeAddOp2(v, OP_Null, 0, 5); + } + sqlite4VdbeAddOp2(v, OP_Integer, pCol->isPrimKey, 6); + sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 6); + } + } + }else + + if( sqlite4_stricmp(zLeft, "index_info")==0 && zRight ){ + Index *pIdx; + Table *pTab; + if( sqlite4ReadSchema(pParse) ) goto pragma_out; + pIdx = sqlite4FindIndex(db, zRight, zDb); + if( pIdx ){ + int i; + pTab = pIdx->pTable; + sqlite4VdbeSetNumCols(v, 3); + pParse->nMem = 3; + sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE4_STATIC); + for(i=0; inColumn; i++){ + int cnum = pIdx->aiColumn[i]; + sqlite4VdbeAddOp2(v, OP_Integer, i, 1); + sqlite4VdbeAddOp2(v, OP_Integer, cnum, 2); + assert( pTab->nCol>cnum ); + sqlite4VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0); + sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 3); + } + } + }else + + if( sqlite4_stricmp(zLeft, "index_list")==0 && zRight ){ + Index *pIdx; + Table *pTab; + if( sqlite4ReadSchema(pParse) ) goto pragma_out; + pTab = sqlite4FindTable(db, zRight, zDb); + if( pTab ){ + v = sqlite4GetVdbe(pParse); + pIdx = pTab->pIndex; + if( pIdx ){ + int i = 0; + sqlite4VdbeSetNumCols(v, 3); + pParse->nMem = 3; + sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE4_STATIC); + while(pIdx){ + sqlite4VdbeAddOp2(v, OP_Integer, i, 1); + sqlite4VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); + sqlite4VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3); + sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 3); + ++i; + pIdx = pIdx->pNext; + } + } + } + }else + + if( sqlite4_stricmp(zLeft, "database_list")==0 ){ + int i; + if( sqlite4ReadSchema(pParse) ) goto pragma_out; + sqlite4VdbeSetNumCols(v, 3); + pParse->nMem = 3; + sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 2, COLNAME_NAME, "file", SQLITE4_STATIC); + for(i=0; inDb; i++){ + if( db->aDb[i].pKV==0 ) continue; + assert( db->aDb[i].zName!=0 ); + sqlite4VdbeAddOp2(v, OP_Integer, i, 1); + sqlite4VdbeAddOp4(v, OP_String8, 0, 2, 0, db->aDb[i].zName, 0); + sqlite4VdbeAddOp4(v, OP_String8, 0, 3, 0, + "filename", 0); + sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 3); + } + }else + + if( sqlite4_stricmp(zLeft, "collation_list")==0 ){ + int i = 0; + HashElem *p; + sqlite4VdbeSetNumCols(v, 2); + pParse->nMem = 2; + sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE4_STATIC); + for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){ + CollSeq *pColl = (CollSeq *)sqliteHashData(p); + sqlite4VdbeAddOp2(v, OP_Integer, i++, 1); + sqlite4VdbeAddOp4(v, OP_String8, 0, 2, 0, pColl->zName, 0); + sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 2); + } + }else +#endif /* SQLITE4_OMIT_SCHEMA_PRAGMAS */ + +#ifndef SQLITE4_OMIT_FOREIGN_KEY + if( sqlite4_stricmp(zLeft, "foreign_key_list")==0 && zRight ){ + FKey *pFK; + Table *pTab; + if( sqlite4ReadSchema(pParse) ) goto pragma_out; + pTab = sqlite4FindTable(db, zRight, zDb); + if( pTab ){ + v = sqlite4GetVdbe(pParse); + pFK = pTab->pFKey; + if( pFK ){ + int i = 0; + sqlite4VdbeSetNumCols(v, 8); + pParse->nMem = 8; + sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "id", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 1, COLNAME_NAME, "seq", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 2, COLNAME_NAME, "table", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 3, COLNAME_NAME, "from", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 4, COLNAME_NAME, "to", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 5, COLNAME_NAME, "on_update", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 6, COLNAME_NAME, "on_delete", SQLITE4_STATIC); + sqlite4VdbeSetColName(v, 7, COLNAME_NAME, "match", SQLITE4_STATIC); + while(pFK){ + int j; + for(j=0; jnCol; j++){ + char *zCol = pFK->aCol[j].zCol; + char *zOnDelete = (char *)actionName(pFK->aAction[0]); + char *zOnUpdate = (char *)actionName(pFK->aAction[1]); + sqlite4VdbeAddOp2(v, OP_Integer, i, 1); + sqlite4VdbeAddOp2(v, OP_Integer, j, 2); + sqlite4VdbeAddOp4(v, OP_String8, 0, 3, 0, pFK->zTo, 0); + sqlite4VdbeAddOp4(v, OP_String8, 0, 4, 0, + pTab->aCol[pFK->aCol[j].iFrom].zName, 0); + sqlite4VdbeAddOp4(v, zCol ? OP_String8 : OP_Null, 0, 5, 0, zCol, 0); + sqlite4VdbeAddOp4(v, OP_String8, 0, 6, 0, zOnUpdate, 0); + sqlite4VdbeAddOp4(v, OP_String8, 0, 7, 0, zOnDelete, 0); + sqlite4VdbeAddOp4(v, OP_String8, 0, 8, 0, "NONE", 0); + sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 8); + } + ++i; + pFK = pFK->pNextFrom; + } + } + } + }else +#endif /* !defined(SQLITE4_OMIT_FOREIGN_KEY) */ + +#ifndef NDEBUG + if( sqlite4_stricmp(zLeft, "parser_trace")==0 ){ + if( zRight ){ + if( sqlite4GetBoolean(zRight) ){ + sqlite4ParserTrace(stderr, "parser: "); + }else{ + sqlite4ParserTrace(0, 0); + } + } + }else +#endif + + /* Reinstall the LIKE and GLOB functions. The variant of LIKE + ** used will be case sensitive or not depending on the RHS. + */ + if( sqlite4_stricmp(zLeft, "case_sensitive_like")==0 ){ + if( zRight ){ + sqlite4RegisterLikeFunctions(db, sqlite4GetBoolean(zRight)); + } + }else + +#ifndef SQLITE4_INTEGRITY_CHECK_ERROR_MAX +# define SQLITE4_INTEGRITY_CHECK_ERROR_MAX 100 +#endif + + +#ifndef SQLITE4_OMIT_UTF16 + /* + ** PRAGMA encoding + ** PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be" + ** + ** In its first form, this pragma returns the encoding of the main + ** database. If the database is not initialized, it is initialized now. + ** + ** The second form of this pragma is a no-op if the main database file + ** has not already been initialized. In this case it sets the default + ** encoding that will be used for the main database file if a new file + ** is created. If an existing main database file is opened, then the + ** default text encoding for the existing database is used. + ** + ** In all cases new databases created using the ATTACH command are + ** created to use the same default text encoding as the main database. If + ** the main database has not been initialized and/or created when ATTACH + ** is executed, this is done before the ATTACH operation. + ** + ** In the second form this pragma sets the text encoding to be used in + ** new database files created using this database handle. It is only + ** useful if invoked immediately after the main database i + */ + if( sqlite4_stricmp(zLeft, "encoding")==0 ){ + static const struct EncName { + char *zName; + u8 enc; + } encnames[] = { + { "UTF8", SQLITE4_UTF8 }, + { "UTF-8", SQLITE4_UTF8 }, /* Must be element [1] */ + { "UTF-16le", SQLITE4_UTF16LE }, /* Must be element [2] */ + { "UTF-16be", SQLITE4_UTF16BE }, /* Must be element [3] */ + { "UTF16le", SQLITE4_UTF16LE }, + { "UTF16be", SQLITE4_UTF16BE }, + { "UTF-16", 0 }, /* SQLITE4_UTF16NATIVE */ + { "UTF16", 0 }, /* SQLITE4_UTF16NATIVE */ + { 0, 0 } + }; + const struct EncName *pEnc; + if( !zRight ){ /* "PRAGMA encoding" */ + if( sqlite4ReadSchema(pParse) ) goto pragma_out; + sqlite4VdbeSetNumCols(v, 1); + sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "encoding", SQLITE4_STATIC); + sqlite4VdbeAddOp2(v, OP_String8, 0, 1); + assert( encnames[SQLITE4_UTF8].enc==SQLITE4_UTF8 ); + assert( encnames[SQLITE4_UTF16LE].enc==SQLITE4_UTF16LE ); + assert( encnames[SQLITE4_UTF16BE].enc==SQLITE4_UTF16BE ); + sqlite4VdbeChangeP4(v, -1, encnames[ENC(pParse->db)].zName, P4_STATIC); + sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 1); + }else{ /* "PRAGMA encoding = XXX" */ + /* Only change the value of sqlite.enc if the database handle is not + ** initialized. If the main database exists, the new sqlite.enc value + ** will be overwritten when the schema is next loaded. If it does not + ** already exists, it will be created to use the new encoding value. + */ + if( + !(DbHasProperty(db, 0, DB_SchemaLoaded)) || + DbHasProperty(db, 0, DB_Empty) + ){ + for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ + if( 0==sqlite4_stricmp(zRight, pEnc->zName) ){ + ENC(pParse->db) = pEnc->enc ? pEnc->enc : SQLITE4_UTF16NATIVE; + break; + } + } + if( !pEnc->zName ){ + sqlite4ErrorMsg(pParse, "unsupported encoding: %s", zRight); + } + } + } + }else +#endif /* SQLITE4_OMIT_UTF16 */ + + +#ifndef SQLITE4_OMIT_COMPILEOPTION_DIAGS + /* + ** PRAGMA compile_options + ** + ** Return the names of all compile-time options used in this build, + ** one option per row. + */ + if( sqlite4_stricmp(zLeft, "compile_options")==0 ){ + int i = 0; + const char *zOpt; + sqlite4VdbeSetNumCols(v, 1); + pParse->nMem = 1; + sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "compile_option", SQLITE4_STATIC); + while( (zOpt = sqlite4_compileoption_get(i++))!=0 ){ + sqlite4VdbeAddOp4(v, OP_String8, 0, 1, 0, zOpt, 0); + sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 1); + } + }else +#endif /* SQLITE4_OMIT_COMPILEOPTION_DIAGS */ + +#ifdef SQLITE4_DEBUG + /* + ** PRAGMA kvdump + ** + ** Print an ascii rendering of the complete content of the database file. + */ + if( sqlite4_stricmp(zLeft, "kvdump")==0 ){ + sqlite4KVStoreDump(db->aDb[0].pKV); + }else +#endif /* SQLITE4_OMIT_COMPILEOPTION_DIAGS */ + /* + ** PRAGMA integrity_check + ** + ** Check that for each table, the content of any auxilliary indexes are + ** consistent with the primary key index. + */ + if( sqlite4_stricmp(zLeft, "integrity_check")==0 ){ + const int baseCsr = 1; /* Base cursor for OpenAllIndexes() call */ + + const int regErrcnt = 1; /* Register containing error count */ + const int regErrstr = 2; /* Register containing error string */ + const int regTmp = 3; /* Register for tmp use */ + const int regRowcnt1 = 4; /* Register containing row count (from PK) */ + const int regRowcnt2 = 5; /* Register containing error count */ + const int regResult = 6; /* Register containing result string */ + const int regKey = 7; /* Register containing encoded key */ + const int regArray = 8; /* First in array of registers */ + + int i; + int nMaxArray = 1; + int addrNot = 0; + Vdbe *v; + + if( sqlite4ReadSchema(pParse) ) goto pragma_out; + + for(i=0; inDb; i++){ + if( OMIT_TEMPDB && i==1 ) continue; + sqlite4CodeVerifySchema(pParse, i); + } + + v = sqlite4GetVdbe(pParse); + sqlite4VdbeAddOp2(v, OP_Integer, 0, regErrcnt); + sqlite4VdbeAddOp4(v, OP_String8, 0, regErrstr, 0, "", 0); + + for(i=0; inDb; i++){ + Hash *pTbls; + HashElem *x; + + if( OMIT_TEMPDB && i==1 ) continue; + + pTbls = &db->aDb[i].pSchema->tblHash; + for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ + Index *pIdx; + Table *pTab = (Table *)sqliteHashData(x); + int addrRewind; + int nIdx = 0; + int iPkCsr; + Index *pPk; + int iCsr; + + /* Do nothing for views */ + if( IsView(pTab) ) continue; + + /* Open all indexes for table pTab. */ + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + if( pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY ){ + pPk = pIdx; + iPkCsr = nIdx+baseCsr; + } + nIdx++; + } + sqlite4OpenAllIndexes(pParse, pTab, baseCsr, OP_OpenRead); + + sqlite4VdbeAddOp2(v, OP_Integer, 0, regRowcnt1); + addrRewind = sqlite4VdbeAddOp1(v, OP_Rewind, iPkCsr); + + /* Increment the row-count register */ + sqlite4VdbeAddOp2(v, OP_AddImm, regRowcnt1, 1); + + for(iCsr=baseCsr, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCsr++){ + assert( (pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY)==(iCsr==iPkCsr) ); + if( iCsr!=iPkCsr ){ + char *zErr; + int iCol; + int jmp; + for(iCol=0; iColnColumn; iCol++){ + int r = regArray + iCol; + sqlite4VdbeAddOp3(v, OP_Column, iPkCsr, pIdx->aiColumn[iCol], r); + assert( pIdx->aiColumn[iCol]>=0 ); + } + for(iCol=0; iColnColumn; iCol++){ + int reg = regArray + pIdx->nColumn + iCol; + int iTblCol = pPk->aiColumn[iCol]; + if( iTblCol<0 ){ + sqlite4VdbeAddOp2(v, OP_Rowid, iPkCsr, reg); + }else{ + sqlite4VdbeAddOp3(v, OP_Column, iPkCsr, iTblCol, reg); + } + } + + if( (pPk->nColumn+pIdx->nColumn)>nMaxArray ){ + nMaxArray = pPk->nColumn + pIdx->nColumn; + } + + sqlite4VdbeAddOp3(v, OP_MakeIdxKey, iCsr, regArray, regKey); + jmp = sqlite4VdbeAddOp4(v, OP_Found, iCsr, 0, regKey, 0, P4_INT32); + sqlite4VdbeAddOp2(v, OP_AddImm, regErrcnt, 1); + zErr = sqlite4MPrintf( + db, "entry missing from index %s: ", pIdx->zName + ); + sqlite4VdbeAddOp4(v, OP_String8, 0, regTmp, 0, zErr, 0); + sqlite4VdbeAddOp3(v, OP_Concat, regTmp, regErrstr, regErrstr); + sqlite4VdbeAddOp3(v, OP_Function, 0, regKey, regTmp); + sqlite4VdbeChangeP4(v, -1, + (char *)sqlite4FindFunction(db, "hex", 3, 1, 0), + P4_FUNCDEF + ); + sqlite4VdbeChangeP5(v, 1); + sqlite4VdbeAddOp3(v, OP_Concat, regTmp, regErrstr, regErrstr); + sqlite4VdbeAddOp4(v, OP_String8, 0, regTmp, 0, "\n", 0); + sqlite4VdbeAddOp3(v, OP_Concat, regTmp, regErrstr, regErrstr); + sqlite4VdbeJumpHere(v, jmp); + sqlite4DbFree(db, zErr); + } + } + sqlite4VdbeAddOp2(v, OP_Next, iPkCsr, addrRewind+1); + sqlite4VdbeJumpHere(v, addrRewind); + + for(iCsr=baseCsr, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCsr++){ + if( iCsr!=iPkCsr ){ + char *zErr; + int addrEq; + int addrRewind2; + sqlite4VdbeAddOp2(v, OP_Integer, 0, regRowcnt2); + addrRewind2 = sqlite4VdbeAddOp1(v, OP_Rewind, iCsr); + sqlite4VdbeAddOp2(v, OP_AddImm, regRowcnt2, 1); + sqlite4VdbeAddOp2(v, OP_Next, iCsr, addrRewind2+1); + sqlite4VdbeJumpHere(v, addrRewind2); + zErr = sqlite4MPrintf( + db, "wrong # number of entries in index %s\n", pIdx->zName + ); + addrEq = sqlite4VdbeAddOp3(v, OP_Eq, regRowcnt1, 0, regRowcnt2); + sqlite4VdbeAddOp2(v, OP_AddImm, regErrcnt, 1); + sqlite4VdbeAddOp4(v, OP_String8, 0, regTmp, 0, zErr, 0); + sqlite4VdbeAddOp3(v, OP_Concat, regTmp, regErrstr, regErrstr); + + sqlite4VdbeJumpHere(v, addrEq); + sqlite4DbFree(db, zErr); + } + } + + for(iCsr=baseCsr; iCsr<(baseCsr+nIdx); iCsr++){ + sqlite4VdbeAddOp1(v, OP_Close, iCsr); + } + } + } + + sqlite4VdbeAddOp4(v, OP_String8, 0, regResult, 0, "ok", 0); + addrNot = sqlite4VdbeAddOp1(v, OP_IfNot, regErrcnt); + sqlite4VdbeAddOp4(v, OP_String8, 0, regArray, 0, " errors:\n", 0); + sqlite4VdbeAddOp3(v, OP_Concat, regArray, regErrcnt, regResult); + sqlite4VdbeAddOp3(v, OP_Concat, regErrstr, regResult, regResult); + sqlite4VdbeJumpHere(v, addrNot); + + pParse->nMem = (regArray + nMaxArray); + sqlite4VdbeSetNumCols(v, 1); + sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE4_STATIC); + sqlite4VdbeAddOp2(v, OP_ResultRow, regResult, 1); + + }else + + + /* + ** PRAGMA shrink_memory + ** + ** This pragma attempts to free as much memory as possible from the + ** current database connection. + */ + if( sqlite4_stricmp(zLeft, "shrink_memory")==0 ){ + sqlite4_db_release_memory(db); + }else + + + {/* Empty ELSE clause */} +pragma_out: + sqlite4DbFree(db, zLeft); + sqlite4DbFree(db, zRight); +} +#endif + #endif /* SQLITE4_OMIT_PRAGMA */ Index: src/prepare.c ================================================================== --- src/prepare.c +++ src/prepare.c @@ -157,25 +157,10 @@ } } return 0; } - -static int createSchemaTable( - InitData *pInit, - const char *zName, - i64 iRoot, - const char *zSchema -){ - Table *pTab; - initCallback(pInit, zName, iRoot, zSchema); - if( pInit->rc ) return 1; - pTab = sqlite4FindTable(pInit->db, zName, pInit->db->aDb[pInit->iDb].zName); - if( ALWAYS(pTab) ) pTab->tabFlags |= TF_Readonly; - return 0; -} - /* ** Attempt to read the database schema and initialize internal ** data structures for a single database file. The index of the ** database file is given by iDb. iDb==0 is used for the main @@ -188,63 +173,66 @@ Table *pTab; Db *pDb; InitData initData; char const *zMasterSchema; char const *zMasterName; - char const *zKvstoreName; int openedTransaction = 0; - static const char *aMaster[] = { + /* + ** The master database table has a structure like this + */ + static const char master_schema[] = "CREATE TABLE sqlite_master(\n" " type text,\n" " name text,\n" " tbl_name text,\n" " rootpage integer,\n" " sql text\n" - ")", + ")" + ; #ifndef SQLITE4_OMIT_TEMPDB + static const char temp_master_schema[] = "CREATE TEMP TABLE sqlite_temp_master(\n" " type text,\n" " name text,\n" " tbl_name text,\n" " rootpage integer,\n" " sql text\n" ")" -#endif - }; - static const char *aKvstore[] = { - "CREATE TABLE sqlite_kvstore(key BLOB PRIMARY KEY, value BLOB)", -#ifndef SQLITE4_OMIT_TEMPDB - "CREATE TABLE sqlite_temp_kvstore(key BLOB PRIMARY KEY, value BLOB)" -#endif - }; - static const char *aKvstoreName[] = { - "sqlite_kvstore", -#ifndef SQLITE4_OMIT_TEMPDB - "sqlite_temp_kvstore" -#endif - }; - + ; +#else + #define temp_master_schema 0 +#endif assert( iDb>=0 && iDbnDb ); assert( db->aDb[iDb].pSchema ); assert( sqlite4_mutex_held(db->mutex) ); - /* zMasterName is the name of the master table. */ + /* zMasterSchema and zInitScript are set to point at the master schema + ** and initialisation script appropriate for the database being + ** initialised. zMasterName is the name of the master table. + */ + if( !OMIT_TEMPDB && iDb==1 ){ + zMasterSchema = temp_master_schema; + }else{ + zMasterSchema = master_schema; + } zMasterName = SCHEMA_TABLE(iDb); - zKvstoreName = aKvstoreName[iDb==1]; /* Construct the schema tables. */ initData.db = db; initData.iDb = iDb; initData.rc = SQLITE4_OK; initData.pzErrMsg = pzErrMsg; - if( createSchemaTable(&initData, zMasterName, 1, aMaster[iDb==1]) - || createSchemaTable(&initData, zKvstoreName, KVSTORE_ROOT, aKvstore[iDb==1]) - ){ + initCallback(&initData, zMasterName, 1, zMasterSchema); + if( initData.rc ){ rc = initData.rc; goto error_out; + } + pTab = sqlite4FindTable(db, zMasterName, db->aDb[iDb].zName); + if( ALWAYS(pTab) ){ + pTab->tabFlags |= TF_Readonly; } /* Create a cursor to hold the database open */ pDb = &db->aDb[iDb]; Index: src/printf.c ================================================================== --- src/printf.c +++ src/printf.c @@ -68,30 +68,30 @@ /* ** The following table is searched linearly, so it is good to put the ** most frequently used conversion types first. */ -static const char aDigits[] = "0123456789abcdef0123456789ABCDEF"; +static const char aDigits[] = "0123456789ABCDEF0123456789abcdef"; static const char aPrefix[] = "-x0\000X0"; static const et_info fmtinfo[] = { { 'd', 10, 1, etRADIX, 0, 0 }, { 's', 0, 4, etSTRING, 0, 0 }, - { 'g', 0, 1, etGENERIC, 14, 0 }, + { 'g', 0, 1, etGENERIC, 30, 0 }, { 'z', 0, 4, etDYNSTRING, 0, 0 }, { 'q', 0, 4, etSQLESCAPE, 0, 0 }, { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, { 'w', 0, 4, etSQLESCAPE3, 0, 0 }, { 'c', 0, 0, etCHARX, 0, 0 }, { 'o', 8, 0, etRADIX, 0, 2 }, { 'u', 10, 0, etRADIX, 0, 0 }, - { 'x', 16, 0, etRADIX, 0, 1 }, - { 'X', 16, 0, etRADIX, 16, 4 }, + { 'x', 16, 0, etRADIX, 16, 1 }, + { 'X', 16, 0, etRADIX, 0, 4 }, #ifndef SQLITE4_OMIT_FLOATING_POINT { 'f', 0, 1, etFLOAT, 0, 0 }, - { 'e', 0, 1, etEXP, 14, 0 }, - { 'E', 0, 1, etEXP, 30, 0 }, - { 'G', 0, 1, etGENERIC, 30, 0 }, + { 'e', 0, 1, etEXP, 30, 0 }, + { 'E', 0, 1, etEXP, 14, 0 }, + { 'G', 0, 1, etGENERIC, 14, 0 }, #endif { 'i', 10, 1, etRADIX, 0, 0 }, { 'n', 0, 0, etSIZE, 0, 0 }, { '%', 0, 0, etPERCENT, 0, 0 }, { 'p', 16, 0, etPOINTER, 0, 1 }, @@ -983,18 +983,5 @@ va_start(ap,zFormat); sqlite4VXPrintf(p, 1, zFormat, ap); va_end(ap); } #endif - -/* -** Convert an N-byte blob into hex. The caller is responsible for making -** sure zOut contains at least N*2+1 bytes of usable space. -*/ -void sqlite4BlobToHex(int N, const u8 *zIn, char *zOut){ - while( (N--)>0 ){ - u8 c = *(zIn++); - *(zOut++) = aDigits[c>>4]; - *(zOut++) = aDigits[c&0x0f]; - } - *zOut = 0; -} Index: src/resolve.c ================================================================== --- src/resolve.c +++ src/resolve.c @@ -364,14 +364,14 @@ ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the ** column number is greater than the number of bits in the bitmask ** then set the high-order bit of the bitmask. */ - if( pMatch!=0 ){ + if( pExpr->iColumn>=0 && pMatch!=0 ){ int n = pExpr->iColumn; testcase( n==BMS-1 ); - if( n>=BMS || n<0 ){ + if( n>=BMS ){ n = BMS-1; } assert( pMatch->iCursor==pExpr->iTable ); pMatch->colUsed |= ((Bitmask)1)<pTab = pItem->pTab; p->iTable = pItem->iCursor; p->iColumn = (ynVar)iCol; testcase( iCol==BMS ); testcase( iCol==BMS-1 ); - pItem->colUsed |= ((Bitmask)1)<<((iCol>=BMS || iCol<0) ? BMS-1 : iCol); + pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol); ExprSetProperty(p, EP_Resolved); } return p; } Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -422,10 +422,11 @@ ){ Vdbe *v = pParse->pVdbe; int nExpr = pOrderBy->nExpr; int regBase = sqlite4GetTempRange(pParse, nExpr+1); int regKey = sqlite4GetTempReg(pParse); + int op; /* Assemble the sort-key values in a contiguous array of registers ** starting at regBase. The sort-key consists of the result of each ** expression in the ORDER BY clause followed by a unique sequence ** number. The sequence number allows more than one row with the same @@ -438,11 +439,16 @@ sqlite4VdbeAddOp3(v, OP_MakeIdxKey, pOrderBy->iECursor, regBase, regKey); /* Insert an entry into the sorter. The key inserted is the encoded key ** created by the OP_MakeIdxKey coded above. The value is the record ** currently stored in register regData. */ - sqlite4VdbeAddOp3(v, OP_Insert, pOrderBy->iECursor, regData, regKey); + if( pSelect->selFlags & SF_UseSorter ){ + op = OP_SorterInsert; + }else{ + op = OP_IdxInsert; + } + sqlite4VdbeAddOp3(v, op, pOrderBy->iECursor, regData, regKey); /* Release the temporary registers */ sqlite4ReleaseTempReg(pParse, regKey); sqlite4ReleaseTempRange(pParse, regBase, nExpr+1); @@ -505,11 +511,11 @@ r1 = sqlite4GetTempReg(pParse); r2 = sqlite4GetTempReg(pParse); sqlite4VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); sqlite4VdbeAddOp2(v, OP_MakeKey, iTab, r2); sqlite4VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); - sqlite4VdbeAddOp3(v, OP_Insert, iTab, r1, r2); + sqlite4VdbeAddOp3(v, OP_IdxInsert, iTab, r1, r2); sqlite4ReleaseTempReg(pParse, r1); sqlite4ReleaseTempReg(pParse, r2); } #ifndef SQLITE4_OMIT_SUBQUERY @@ -623,11 +629,11 @@ int r1, r2; r1 = sqlite4GetTempReg(pParse); r2 = sqlite4GetTempReg(pParse); sqlite4VdbeAddOp2(v, OP_MakeKey, iParm, r2); sqlite4VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); - sqlite4VdbeAddOp3(v, OP_Insert, iParm, r1, r2); + sqlite4VdbeAddOp3(v, OP_IdxInsert, iParm, r1, r2); sqlite4ReleaseTempReg(pParse, r1); sqlite4ReleaseTempReg(pParse, r2); break; } @@ -687,11 +693,11 @@ }else{ int r2 = sqlite4GetTempReg(pParse); sqlite4VdbeAddOp2(v, OP_MakeKey, iParm, r2); sqlite4VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1); sqlite4ExprCacheAffinityChange(pParse, regResult, 1); - sqlite4VdbeAddOp3(v, OP_Insert, iParm, r1, r2); + sqlite4VdbeAddOp3(v, OP_IdxInsert, iParm, r1, r2); sqlite4ReleaseTempReg(pParse, r2); } sqlite4ReleaseTempReg(pParse, r1); break; } @@ -801,10 +807,12 @@ if( pInfo ){ int i; /* Used to iterate through pList */ pInfo->aSortOrder = (u8*)&pInfo->aColl[nField]; pInfo->nField = (u16)nField; + pInfo->enc = ENC(db); + pInfo->db = db; for(i=0; inExpr; i++){ CollSeq *pColl; pColl = sqlite4ExprCollSeq(pParse, pList->a[i].pExpr); if( !pColl ) pColl = db->pDfltColl; @@ -918,46 +926,57 @@ int addrBreak = sqlite4VdbeMakeLabel(v); /* Jump here to exit loop */ int addrContinue = sqlite4VdbeMakeLabel(v); /* Jump here for next cycle */ int addr; int iTab; /* Sorter object cursor */ ExprList *pOrderBy = p->pOrderBy; + int eDest = pDest->eDest; int iParm = pDest->iParm; - int op; /* Opcode use to sort results */ + + int regRow; + int regRowid = 0; iTab = pOrderBy->iECursor; - op = (p->selFlags & SF_UseSorter) ? OP_SorterSort : OP_Sort; - addr = 1 + sqlite4VdbeAddOp2(v, op, iTab, addrBreak); - codeOffset(v, p, addrContinue); + regRow = sqlite4GetTempReg(pParse); + if( eDest!=SRT_Output && eDest!=SRT_Coroutine ){ + regRowid = sqlite4GetTempReg(pParse); + } + + if( p->selFlags & SF_UseSorter ){ + int regSortOut = ++pParse->nMem; + int ptab2 = pParse->nTab++; + sqlite4VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, pOrderBy->nExpr+2); + addr = 1 + sqlite4VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); + codeOffset(v, p, addrContinue); + sqlite4VdbeAddOp2(v, OP_SorterData, iTab, regSortOut); + sqlite4VdbeAddOp3(v, OP_Column, ptab2, 0, regRow); + sqlite4VdbeChangeP5(v, OPFLAG_CLEARCACHE); + }else{ + addr = 1 + sqlite4VdbeAddOp2(v, OP_Sort, iTab, addrBreak); + codeOffset(v, p, addrContinue); + sqlite4VdbeAddOp3(v, OP_Column, iTab, 0, regRow); + } switch( eDest ){ case SRT_Table: case SRT_EphemTab: { - int regRowid = sqlite4GetTempReg(pParse); - int regRow = sqlite4GetTempReg(pParse); testcase( eDest==SRT_Table ); testcase( eDest==SRT_EphemTab ); sqlite4VdbeAddOp2(v, OP_NewRowid, iParm, regRowid); sqlite4VdbeAddOp2(v, OP_RowData, iTab, regRow); sqlite4VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid); sqlite4VdbeChangeP5(v, OPFLAG_APPEND); - sqlite4ReleaseTempReg(pParse, regRow); - sqlite4ReleaseTempReg(pParse, regRowid); break; } #ifndef SQLITE4_OMIT_SUBQUERY case SRT_Set: { - int regRes = sqlite4GetTempReg(pParse); - int regKey = sqlite4GetTempReg(pParse); - int regValue = sqlite4GetTempReg(pParse); assert( nColumn==1 ); - sqlite4VdbeAddOp3(v, OP_Column, iTab, 0, regRes); + int regKey = sqlite4GetTempReg(pParse); sqlite4VdbeAddOp2(v, OP_MakeKey, iParm, regKey); - sqlite4VdbeAddOp4(v, OP_MakeRecord, regRes, 1, regValue, &p->affinity, 1); - sqlite4VdbeAddOp3(v, OP_Insert, iParm, regValue, regKey); + sqlite4VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &p->affinity, 1); + sqlite4ExprCacheAffinityChange(pParse, regRow, 1); + sqlite4VdbeAddOp3(v, OP_IdxInsert, iParm, regRowid, regKey); sqlite4ReleaseTempReg(pParse, regKey); - sqlite4ReleaseTempReg(pParse, regRes); - sqlite4ReleaseTempReg(pParse, regValue); break; } case SRT_Mem: { assert( nColumn==1 ); sqlite4VdbeAddOp3(v, OP_Column, iTab, 0, iParm); @@ -984,10 +1003,12 @@ sqlite4VdbeAddOp1(v, OP_Yield, pDest->iParm); } break; } } + sqlite4ReleaseTempReg(pParse, regRow); + sqlite4ReleaseTempReg(pParse, regRowid); /* The bottom of the loop */ sqlite4VdbeResolveLabel(v, addrContinue); if( p->selFlags & SF_UseSorter ){ @@ -1868,10 +1889,11 @@ if( !pKeyInfo ){ rc = SQLITE4_NOMEM; goto multi_select_end; } + pKeyInfo->enc = ENC(db); pKeyInfo->nField = (u16)nCol; for(i=0, apColl=pKeyInfo->aColl; iiParm, r2); sqlite4VdbeAddOp4(v, OP_MakeRecord, pIn->iMem, 1, r1, &p->affinity, 1); sqlite4ExprCacheAffinityChange(pParse, pIn->iMem, 1); - sqlite4VdbeAddOp3(v, OP_Insert, pDest->iParm, r1, r2); + sqlite4VdbeAddOp3(v, OP_IdxInsert, pDest->iParm, r1, r2); sqlite4ReleaseTempReg(pParse, r1); sqlite4ReleaseTempReg(pParse, r2); break; } @@ -2252,10 +2274,11 @@ pKeyMerge = sqlite4DbMallocRaw(db, sizeof(*pKeyMerge)+nOrderBy*(sizeof(CollSeq*)+1)); if( pKeyMerge ){ pKeyMerge->aSortOrder = (u8*)&pKeyMerge->aColl[nOrderBy]; pKeyMerge->nField = (u16)nOrderBy; + pKeyMerge->enc = ENC(db); for(i=0; ia[i].pExpr; if( pTerm->flags & EP_ExpCollate ){ pColl = pTerm->pColl; @@ -2292,10 +2315,11 @@ pKeyDup = sqlite4DbMallocZero(db, sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq*)+1) ); if( pKeyDup ){ pKeyDup->aSortOrder = (u8*)&pKeyDup->aColl[nExpr]; pKeyDup->nField = (u16)nExpr; + pKeyDup->enc = ENC(db); for(i=0; iaColl[i] = multiSelectCollSeq(pParse, p, i); pKeyDup->aSortOrder[i] = 0; } } @@ -2460,12 +2484,11 @@ sqlite4VdbeAddOp2(v, OP_If, regEofB, addrEofB); /* Implement the main merge loop */ sqlite4VdbeResolveLabel(v, labelCmpr); - sqlite4VdbeAddOp4(v, OP_Permutation, nOrderBy, 0, 0, - (char*)aPermute, P4_INTARRAY); + sqlite4VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); sqlite4VdbeAddOp4(v, OP_Compare, destA.iMem, destB.iMem, nOrderBy, (char*)pKeyMerge, P4_KEYINFO_HANDOFF); sqlite4VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); /* Jump to the this point in order to terminate the query. @@ -3933,16 +3956,13 @@ /* Aggregate and non-aggregate queries are handled differently */ if( !isAgg && pGroupBy==0 ){ ExprList *pDist = (isDistinct ? p->pEList : 0); /* Begin the database scan. */ - pWInfo = sqlite4WhereBegin(pParse, pTabList, pWhere, pOrderBy, pDist, 0, 0); + pWInfo = sqlite4WhereBegin(pParse, pTabList, pWhere, &pOrderBy, pDist, 0); if( pWInfo==0 ) goto select_end; - if( sqlite4WhereOutputRowCount(pWInfo)nSelectRow ){ - p->nSelectRow = sqlite4WhereOutputRowCount(pWInfo); - } - if( pOrderBy && sqlite4WhereIsOrdered(pWInfo) ) pOrderBy = 0; + if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut; /* If sorting index that was created by a prior OP_OpenEphemeral ** instruction ended up not being needed, then change the OP_OpenEphemeral ** into an OP_Noop. */ @@ -3949,22 +3969,22 @@ if( addrSortIndex>=0 && pOrderBy==0 ){ sqlite4VdbeChangeToNoop(v, addrSortIndex); p->addrOpenEphm[2] = -1; } - if( sqlite4WhereIsDistinct(pWInfo) ){ + if( pWInfo->eDistinct ){ VdbeOp *pOp; /* No longer required OpenEphemeral instr. */ assert( addrDistinctIndex>=0 ); pOp = sqlite4VdbeGetOp(v, addrDistinctIndex); assert( isDistinct ); - assert( sqlite4WhereIsDistinct(pWInfo)==WHERE_DISTINCT_ORDERED - || sqlite4WhereIsDistinct(pWInfo)==WHERE_DISTINCT_UNIQUE + assert( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED + || pWInfo->eDistinct==WHERE_DISTINCT_UNIQUE ); distinct = -1; - if( sqlite4WhereIsDistinct(pWInfo)==WHERE_DISTINCT_ORDERED ){ + if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED ){ int iJump; int iExpr; int iFlag = ++pParse->nMem; int iBase = pParse->nMem+1; int iBase2 = iBase + pEList->nExpr; @@ -3983,11 +4003,11 @@ CollSeq *pColl = sqlite4ExprCollSeq(pParse, pEList->a[iExpr].pExpr); sqlite4VdbeAddOp3(v, OP_Ne, iBase+iExpr, iJump, iBase2+iExpr); sqlite4VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ); sqlite4VdbeChangeP5(v, SQLITE4_NULLEQ); } - sqlite4VdbeAddOp2(v, OP_Goto, 0, sqlite4WhereContinueLabel(pWInfo)); + sqlite4VdbeAddOp2(v, OP_Goto, 0, pWInfo->iContinue); sqlite4VdbeAddOp2(v, OP_Integer, 0, iFlag); assert( sqlite4VdbeCurrentAddr(v)==iJump ); sqlite4VdbeAddOp3(v, OP_Move, iBase, iBase2, pEList->nExpr); }else{ @@ -3995,12 +4015,11 @@ } } /* Use the standard inner loop. */ selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, pDest, - sqlite4WhereContinueLabel(pWInfo), sqlite4WhereBreakLabel(pWInfo) - ); + pWInfo->iContinue, pWInfo->iBreak); /* End the database scan loop. */ sqlite4WhereEnd(pWInfo); }else{ @@ -4106,17 +4125,18 @@ ** This might involve two separate loops with an OP_Sort in between, or ** it might be a single loop that uses an index to extract information ** in the right order to begin with. */ sqlite4VdbeAddOp2(v, OP_Gosub, regReset, addrReset); - pWInfo = sqlite4WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, 0, 0); + pWInfo = sqlite4WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0); if( pWInfo==0 ) goto select_end; - if( sqlite4WhereIsOrdered(pWInfo) ){ + if( pGroupBy==0 ){ /* The optimizer is able to deliver rows in group by order so ** we do not have to sort. The OP_OpenEphemeral table will be - ** cancelled later because we still need to use the pKeyInfo. + ** cancelled later because we still need to use the pKeyInfo */ + pGroupBy = p->pGroupBy; groupBySort = 0; /* Evaluate the current GROUP BY terms and store in b0, b1, b2... ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth) ** Then compare the current GROUP BY terms against the GROUP BY terms @@ -4182,11 +4202,11 @@ } /* Insert the key/value into the sorting index and end the loop ** generated by where.c code. */ sqlite4VdbeAddOp3( - v, OP_Insert, sAggInfo.sortingIdx, regRecord, regKey + v, OP_SorterInsert, sAggInfo.sortingIdx, regRecord, regKey ); sqlite4WhereEnd(pWInfo); sqlite4VdbeAddOp2(v, OP_Null, 0, regKey); sqlite4VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd); @@ -4317,18 +4337,18 @@ /* This case runs if the aggregate has no GROUP BY clause. The ** processing is much simpler since there is only a single row ** of output. */ resetAccumulator(pParse, &sAggInfo); - pWInfo = sqlite4WhereBegin(pParse, pTabList, pWhere, pMinMax, 0,flag,0); + pWInfo = sqlite4WhereBegin(pParse, pTabList, pWhere, &pMinMax, 0, flag); if( pWInfo==0 ){ sqlite4ExprListDelete(db, pDel); goto select_end; } updateAccumulator(pParse, &sAggInfo); - if( sqlite4WhereIsOrdered(pWInfo) && flag ){ - sqlite4VdbeAddOp2(v, OP_Goto, 0, sqlite4WhereBreakLabel(pWInfo)); + if( !pMinMax && flag ){ + sqlite4VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak); VdbeComment((v, "%s() by index", (flag==WHERE_ORDERBY_MIN?"min":"max"))); } sqlite4WhereEnd(pWInfo); finalizeAggFunctions(pParse, &sAggInfo); Index: src/sqlite.h.in ================================================================== --- src/sqlite.h.in +++ src/sqlite.h.in @@ -619,12 +619,10 @@ #define SQLITE4_NOLFS 22 /* Uses OS features not supported on host */ #define SQLITE4_AUTH 23 /* Authorization denied */ #define SQLITE4_FORMAT 24 /* Auxiliary database format error */ #define SQLITE4_RANGE 25 /* 2nd param to sqlite4_bind out of range */ #define SQLITE4_NOTADB 26 /* File opened that is not a database file */ -#define SQLITE4_NOTICE 27 /* Notifications from sqlite4_log() */ -#define SQLITE4_WARNING 28 /* Warnings from sqlite4_log() */ #define SQLITE4_ROW 100 /* sqlite4_step() has another row ready */ #define SQLITE4_DONE 101 /* sqlite4_step() has finished executing */ #define SQLITE4_INEXACT 102 /* xSeek method of storage finds nearby ans */ /* @@ -676,11 +674,10 @@ #define SQLITE4_BUSY_RECOVERY (SQLITE4_BUSY | (1<<8)) #define SQLITE4_CANTOPEN_NOTEMPDIR (SQLITE4_CANTOPEN | (1<<8)) #define SQLITE4_CORRUPT_VTAB (SQLITE4_CORRUPT | (1<<8)) #define SQLITE4_READONLY_RECOVERY (SQLITE4_READONLY | (1<<8)) #define SQLITE4_READONLY_CANTLOCK (SQLITE4_READONLY | (2<<8)) -#define SQLITE4_WARNING_AUTOINDEX (SQLITE4_WARNING | (1<<8)) /* ** CAPIREF: Flags For File Open Operations ** ** These bit values are intended for use as options in the Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -15,10 +15,11 @@ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ #define SQLITE4_OMIT_PROGRESS_CALLBACK 1 #define SQLITE4_OMIT_VIRTUALTABLE 1 +#define SQLITE4_OMIT_XFER_OPT 1 #define SQLITE4_OMIT_LOCALTIME 1 /* ** These #defines should enable >2GB file support on POSIX if the ** underlying operating system supports it. If the OS lacks @@ -298,11 +299,10 @@ #include #include #include #include #include -#include /* FIXME - can we omit this one? */ /* ** If compiling for a processor that lacks floating point support, ** substitute integer for floating-point */ @@ -347,16 +347,10 @@ */ #ifndef offsetof #define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD)) #endif -/* -** Macros to compute minimum and maximum of two numbers. -*/ -#define MIN(A,B) ((A)<(B)?(A):(B)) -#define MAX(A,B) ((A)>(B)?(A):(B)) - /* ** Check to see if this machine uses EBCDIC. (Yes, believe it or ** not, there are still machines out there that use EBCDIC.) */ #if 'A' == '\301' @@ -523,13 +517,10 @@ /* ** The root-page of the master database table. */ #define MASTER_ROOT 1 -#define KVSTORE_ROOT 0x7fffffff - -#define IsKvstore(pTab) ((pTab)->pIndex && (pTab)->pIndex->tnum==KVSTORE_ROOT) /* ** The name of the schema table. */ #define SCHEMA_TABLE(x) ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME) @@ -538,15 +529,10 @@ ** A convenience macro that returns the number of elements in ** an array. */ #define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0]))) -/* -** Determine if the argument is a power of two -*/ -#define IsPowerOfTwo(X) (((X)&((X)-1))==0) - /* ** The following macros are used to suppress compiler warnings and to ** make it clear to human readers when a function parameter is deliberately ** left unused within the body of a function. This usually happens when ** a function is called via a function pointer. For example the @@ -611,10 +597,11 @@ typedef struct Table Table; typedef struct Token Token; typedef struct Trigger Trigger; typedef struct TriggerPrg TriggerPrg; typedef struct TriggerStep TriggerStep; +typedef struct UnpackedRecord UnpackedRecord; typedef struct VTable VTable; typedef struct VtabCtx VtabCtx; typedef struct Walker Walker; typedef struct WherePlan WherePlan; typedef struct WhereInfo WhereInfo; @@ -934,17 +921,10 @@ #define SQLITE4_FactorOutConst 0x40 /* Disable factoring out constants */ #define SQLITE4_IdxRealAsInt 0x80 /* Store REAL as INT in indices */ #define SQLITE4_DistinctOpt 0x80 /* DISTINCT using indexes */ #define SQLITE4_OptMask 0xff /* Mask of all disablable opts */ -/* -** Some new things pulled in from SQLite3 use these macros. todo: Replace -** them with working versions. -*/ -#define OptimizationDisabled(db, mask) 0 -#define OptimizationEnabled(db, mask) 1 - /* ** Possible values for the sqlite.magic field. ** The numbers are obtained at random and have no special meaning, other ** than being distinct from one another. */ @@ -1043,12 +1023,12 @@ char *zName; /* Name of this column */ Expr *pDflt; /* Default value of this column */ char *zDflt; /* Original text of the default value */ char *zType; /* Data type for this column */ char *zColl; /* Collating sequence. If NULL, use the default */ - u16 iPrimKey; /* Index of in the primary key. 0 if not part of PK */ u8 notNull; /* True if there is a NOT NULL constraint */ + u8 isPrimKey; /* True if this column is part of the PRIMARY KEY */ char affinity; /* One of the SQLITE4_AFF_... values */ #ifndef SQLITE4_OMIT_VIRTUALTABLE u8 isHidden; /* True if this column is 'hidden' */ #endif }; @@ -1319,17 +1299,48 @@ ** An instance of the following structure describes an index key. It ** includes information such as sort order and collating sequence for ** each key, and the number of primary key fields appended to the end. */ struct KeyInfo { + sqlite4 *db; /* The database connection */ + u8 enc; /* Text encoding - one of the SQLITE4_UTF* values */ u16 nField; /* Total number of entries in aColl[] */ u16 nPK; /* Number of primary key entries at the end of aColl[] */ u16 nData; /* Number of columns of data in KV entry value */ u8 *aSortOrder; /* Sort order for each column. May be NULL */ CollSeq *aColl[1]; /* Collating sequence for each term of the key */ }; +/* +** An instance of the following structure holds information about a +** single index record that has already been parsed out into individual +** values. +** +** A record is an object that contains one or more fields of data. +** Records are used to store the content of a table row and to store +** the key of an index. A blob encoding of a record is created by +** the OP_MakeRecord opcode of the VDBE and is disassembled by the +** OP_Column opcode. +** +** This structure holds a record that has already been disassembled +** into its constituent fields. +*/ +struct UnpackedRecord { + KeyInfo *pKeyInfo; /* Collation and sort-order information */ + u16 nField; /* Number of entries in apMem[] */ + u8 flags; /* Boolean settings. UNPACKED_... below */ + i64 rowid; /* Used by UNPACKED_PREFIX_SEARCH */ + Mem *aMem; /* Values */ +}; + +/* +** Allowed values of UnpackedRecord.flags +*/ +#define UNPACKED_INCRKEY 0x01 /* Make this key an epsilon larger */ +#define UNPACKED_PREFIX_MATCH 0x02 /* A prefix match is considered OK */ +#define UNPACKED_PREFIX_SEARCH 0x04 /* Ignore final (rowid) field */ + /* ** Each SQL index is represented in memory by an ** instance of the following structure. ** ** The columns of the table that are to be indexed are described @@ -1356,12 +1367,10 @@ */ struct Index { char *zName; /* Name of this index */ int nColumn; /* Number of columns in the table used by this index */ int *aiColumn; /* Which columns are used by this index. 1st is 0 */ - int nCover; /* Number of covering columns in this index */ - int *aiCover; /* Which columns are covered by this index */ tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */ Table *pTable; /* The SQL table being indexed */ int tnum; /* Page containing root of this index in database file */ u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ u8 eIndexType; /* SQLITE4_INDEX_USER, UNIQUE or PRIMARYKEY */ @@ -1375,12 +1384,10 @@ int nSample; /* Number of elements in aSample[] */ tRowcnt avgEq; /* Average nEq value for key values not in aSample */ IndexSample *aSample; /* Samples of the left-most key */ #endif Fts5Index *pFts; /* Fts5 data (or NULL if this is not an fts index) */ - - unsigned bUnordered:1; /* Use this index for == or IN queries only */ }; /* Index.eIndexType must be set to one of the following. */ #define SQLITE4_INDEX_USER 0 /* Index created by CREATE INDEX statement */ #define SQLITE4_INDEX_UNIQUE 1 /* Index created by UNIQUE constraint */ @@ -1790,12 +1797,11 @@ ** and the next table on the list. The parser builds the list this way. ** But sqlite4SrcListShiftJoinType() later shifts the jointypes so that each ** jointype expresses the join between the table and the previous table. ** ** In the colUsed field, the high-order bit (bit 63) is set if the table -** contains more than 63 columns and the 64-th or later column is used, or -** if the table uses an implicit primary key and it is accessed. +** contains more than 63 columns and the 64-th or later column is used. */ struct SrcList { i16 nSrc; /* Number of tables or subqueries in the FROM clause */ i16 nAlloc; /* Number of entries allocated in a[] below */ SrcListItem a[1]; /* One entry for each identifier on the list */ @@ -1836,11 +1842,10 @@ struct WhereTerm *pTerm; /* WHERE clause term for OR-search */ sqlite4_index_info *pVtabIdx; /* Virtual table index to use */ } u; }; -#if 0 /* ** For each nested loop in a WHERE clause implementation, the WhereInfo ** structure contains a single instance of this structure. This structure ** is intended to be private the the where.c module and should not be ** access or modified by other modules. @@ -1880,13 +1885,11 @@ ** a convenient place since there is one WhereLevel for each FROM clause ** element. */ sqlite4_index_info *pIdxInfo; /* Index info for n-th source table */ }; -#endif -#if 0 /* ** Flags appropriate for the wctrlFlags parameter of sqlite4WhereBegin() ** and the WhereInfo.wctrlFlags member. */ #define WHERE_ORDERBY_NORMAL 0x0000 /* No-op */ @@ -1896,40 +1899,18 @@ #define WHERE_DUPLICATES_OK 0x0008 /* Ok to return a row more than once */ #define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */ #define WHERE_NO_AUTOINDEX 0x0020 /* Do not use an auto-index search */ #define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */ #define WHERE_AND_ONLY 0x0080 /* Don't use indices for OR terms */ -#endif - - -/* -** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin() -** and the WhereInfo.wctrlFlags member. -*/ -#define WHERE_ORDERBY_NORMAL 0x0000 /* No-op */ -#define WHERE_ORDERBY_MIN 0x0001 /* ORDER BY processing for min() func */ -#define WHERE_ORDERBY_MAX 0x0002 /* ORDER BY processing for max() func */ -#define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */ -#define WHERE_DUPLICATES_OK 0x0008 /* Ok to return a row more than once */ -#define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */ -#define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */ -#define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */ -#define WHERE_AND_ONLY 0x0080 /* Don't use indices for OR terms */ -#define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */ -#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */ -#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */ - - /* ** The WHERE clause processing routine has two halves. The ** first part does the start of the WHERE loop and the second ** half does the tail of the WHERE loop. An instance of ** this structure is returned by the first half and passed ** into the second half to give some continuity. */ -#if 0 struct WhereInfo { Parse *pParse; /* Parsing and code generating context */ u16 wctrlFlags; /* Flags originally passed to sqlite4WhereBegin() */ u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */ u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ @@ -1942,16 +1923,13 @@ struct WhereClause *pWC; /* Decomposition of the WHERE clause */ double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ double nRowOut; /* Estimated number of output rows */ WhereLevel a[1]; /* Information about each nest loop in WHERE */ }; -#endif -#define WHERE_DISTINCT_NOOP 0 -#define WHERE_DISTINCT_UNIQUE 1 -#define WHERE_DISTINCT_ORDERED 2 -#define WHERE_DISTINCT_UNORDERED 3 +#define WHERE_DISTINCT_UNIQUE 1 +#define WHERE_DISTINCT_ORDERED 2 /* ** A NameContext defines a context in which to resolve table and column ** names. The context consists of a list of tables (the pSrcList) field and ** a list of named expression (pEList). The named expression list may @@ -2513,10 +2491,18 @@ */ #if defined(SQLITE4_ENABLE_FTS4) && !defined(SQLITE4_ENABLE_FTS3) # define SQLITE4_ENABLE_FTS3 #endif +/* +** The ctype.h header is needed for non-ASCII systems. It is also +** needed by FTS3 when FTS3 is included in the amalgamation. +*/ +#if !defined(SQLITE4_ASCII) || \ + (defined(SQLITE4_ENABLE_FTS3) && defined(SQLITE4_AMALGAMATION)) +# include +#endif /* ** The following macros mimic the standard library functions toupper(), ** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The ** sqlite versions only work for ASCII characters, regardless of locale. @@ -2604,11 +2590,10 @@ #else # define sqlite4IsNaN(X) 0 # define sqlite4IsInf(X) 0 #endif -void sqlite4BlobToHex(int, const u8*, char*); void sqlite4VXPrintf(StrAccum*, int, const char*, va_list); #ifndef SQLITE4_OMIT_TRACE void sqlite4XPrintf(StrAccum*, const char*, ...); #endif char *sqlite4MPrintf(sqlite4*,const char*, ...); @@ -2723,11 +2708,12 @@ int sqlite4IndexedByLookup(Parse *, SrcListItem *); void sqlite4SrcListShiftJoinType(SrcList*); void sqlite4SrcListAssignCursors(Parse*, SrcList*); void sqlite4IdListDelete(sqlite4*, IdList*); void sqlite4SrcListDelete(sqlite4*, SrcList*); -Index *sqlite4CreateIndex(Parse*,CreateIndex*,ExprList*,IdList*,int,Token*,int,int); +Index *sqlite4CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, + Token*, int, int, int); void sqlite4DropIndex(Parse*, SrcList*, int); int sqlite4Select(Parse*, Select*, SelectDest*); Select *sqlite4SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, Expr*,ExprList*,int,Expr*,Expr*); void sqlite4SelectDelete(sqlite4*, Select*); @@ -2738,19 +2724,12 @@ && !defined(SQLITE4_OMIT_SUBQUERY) Expr *sqlite4LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*); #endif void sqlite4DeleteFrom(Parse*, SrcList*, Expr*); void sqlite4Update(Parse*, SrcList*, ExprList*, Expr*, int); -WhereInfo *sqlite4WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int); - +WhereInfo *sqlite4WhereBegin(Parse*, SrcList*, Expr*, ExprList**,ExprList*,u16); void sqlite4WhereEnd(WhereInfo*); -u64 sqlite4WhereOutputRowCount(WhereInfo*); -int sqlite4WhereIsDistinct(WhereInfo*); -int sqlite4WhereIsOrdered(WhereInfo*); -int sqlite4WhereContinueLabel(WhereInfo*); -int sqlite4WhereBreakLabel(WhereInfo*); -int sqlite4WhereOkOnePass(WhereInfo*); int sqlite4ExprCodeGetColumn(Parse*, Table*, int, int, int); void sqlite4ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int); void sqlite4ExprCodeMove(Parse*, int, int, int); void sqlite4ExprCodeCopy(Parse*, int, int, int); void sqlite4ExprCacheStore(Parse*, int, int, int); @@ -2778,10 +2757,13 @@ int sqlite4ExprCompare(Expr*, Expr*); int sqlite4ExprListCompare(ExprList*, ExprList*); void sqlite4ExprAnalyzeAggregates(NameContext*, Expr*); void sqlite4ExprAnalyzeAggList(NameContext*,ExprList*); Vdbe *sqlite4GetVdbe(Parse*); +void sqlite4PrngSaveState(void); +void sqlite4PrngRestoreState(void); +void sqlite4PrngResetState(void); void sqlite4CodeVerifySchema(Parse*, int); void sqlite4CodeVerifyNamedSchema(Parse*, const char *zDb); void sqlite4BeginTransaction(Parse*, int); void sqlite4EndTransaction(Parse *, int); void sqlite4Savepoint(Parse*, int, Token*); @@ -2794,11 +2776,10 @@ void sqlite4ExprCodeIsNullJump(Vdbe*, const Expr*, int, int); int sqlite4ExprNeedsNoAffinityChange(const Expr*, char); void sqlite4GenerateRowDelete(Parse*, Table*, int, int, int, Trigger *, int); void sqlite4GenerateRowIndexDelete(Parse*, Table*, int, int, int*); void sqlite4EncodeIndexKey(Parse *, Index *, int, Index *, int, int, int); -void sqlite4EncodeIndexValue(Parse*, int, Index*, int); void sqlite4GenerateConstraintChecks(Parse*,Table*,int,int, int*,int,int,int,int,int*); void sqlite4CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int); int sqlite4OpenTableAndIndices(Parse*, Table*, int, int); void sqlite4BeginWriteOperation(Parse*, int, int); @@ -2882,10 +2863,11 @@ int sqlite4FixSrcList(DbFixer*, SrcList*); int sqlite4FixSelect(DbFixer*, Select*); int sqlite4FixExpr(DbFixer*, Expr*); int sqlite4FixExprList(DbFixer*, ExprList*); int sqlite4FixTriggerStep(DbFixer*, TriggerStep*); +int sqlite4AtoF(const char *z, double*, int, u8); int sqlite4GetInt32(const char *, int*); int sqlite4Atoi(const char*); int sqlite4Utf16ByteLen(const void *pData, int nChar); int sqlite4Utf8CharLen(const char *pData, int nByte); u32 sqlite4Utf8Read(const char*, const char**); @@ -2898,11 +2880,11 @@ ** the MACRO form does). */ int sqlite4PutVarint(unsigned char*, u64); int sqlite4PutVarint32(unsigned char*, u32); u8 sqlite4GetVarint(const unsigned char *, u64 *); -int sqlite4GetVarint32(const unsigned char *, u32 *); +u8 sqlite4GetVarint32(const unsigned char *, u32 *); int sqlite4VarintLen(u64 v); int sqlite4GetVarint64(const unsigned char*, int, sqlite4_uint64 *pResult); int sqlite4PutVarint64(unsigned char*, sqlite4_uint64); /* @@ -2980,17 +2962,18 @@ extern const unsigned char sqlite4CtypeMap[]; extern const Token sqlite4IntTokens[]; extern struct sqlite4_env sqlite4DefaultEnv; extern struct KVFactory sqlite4BuiltinFactory; #endif +void sqlite4RootPageMoved(sqlite4*, int, int, int); void sqlite4Reindex(Parse*, Token*, Token*); void sqlite4AlterFunctions(sqlite4_env*); void sqlite4AlterRenameTable(Parse*, SrcList*, Token*); int sqlite4GetToken(const unsigned char *, int *); void sqlite4NestedParse(Parse*, const char*, ...); void sqlite4ExpirePreparedStatements(sqlite4*); -int sqlite4CodeSubselect(Parse *, Expr *, int); +int sqlite4CodeSubselect(Parse *, Expr *, int, int); void sqlite4SelectPrep(Parse*, Select*, NameContext*); int sqlite4ResolveExprNames(NameContext*, Expr*); void sqlite4ResolveSelectNames(Parse*, Select*, NameContext*); int sqlite4ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); void sqlite4ColumnDefault(Vdbe *, Table *, int, int); @@ -3039,10 +3022,17 @@ void sqlite4ParserFree(void*, void(*)(void*,void*)); void sqlite4Parser(void*, int, Token, Parse*); #ifdef YYTRACKMAXSTACKDEPTH int sqlite4ParserStackPeak(void*); #endif + +void sqlite4AutoLoadExtensions(sqlite4*); +#ifndef SQLITE4_OMIT_LOAD_EXTENSION + void sqlite4CloseExtensions(sqlite4*); +#else +# define sqlite4CloseExtensions(X) +#endif #ifdef SQLITE4_TEST int sqlite4Utf8To8(char*); #endif @@ -3083,10 +3073,14 @@ int sqlite4VdbeParameterIndex(Vdbe*, const char*, int); int sqlite4TransferBindings(sqlite4_stmt *, sqlite4_stmt *); int sqlite4Reprepare(Vdbe*); void sqlite4ExprListCheckLength(Parse*, ExprList*, const char*); CollSeq *sqlite4BinaryCompareCollSeq(Parse *, Expr *, Expr *); +int sqlite4TempInMemory(const sqlite4*); +const char *sqlite4JournalModename(int); +int sqlite4Checkpoint(sqlite4*, int, int, int*, int*); +int sqlite4WalDefaultHook(void*,sqlite4*,const char*,int); /* Declarations for functions in fkey.c. All of these are replaced by ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign ** key functionality is available. If OMIT_TRIGGER is defined but ** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In @@ -3133,13 +3127,12 @@ #define sqlite4EndBenignMalloc(X) #endif #define IN_INDEX_ROWID 1 #define IN_INDEX_EPH 2 -#define IN_INDEX_INDEX_ASC 3 -#define IN_INDEX_INDEX_DESC 4 -int sqlite4FindInIndex(Parse *, Expr *, int*, int*); +#define IN_INDEX_INDEX 3 +int sqlite4FindInIndex(Parse *, Expr *, int*); Index *sqlite4FindExistingInIndex(Parse *, Expr *, int); #if SQLITE4_MAX_EXPR_DEPTH>0 void sqlite4ExprSetHeight(Parse *pParse, Expr *p); Index: src/update.c ================================================================== --- src/update.c +++ src/update.c @@ -341,13 +341,13 @@ ** clause indicates that the loop will visit at most one row, then the ** RowSet object is bypassed and the primary key of the single row (if ** any) left in register regOldKey. This is called the "one-pass" ** approach. Set okOnePass to true if it can be used in this case. */ sqlite4VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldKey); - pWInfo = sqlite4WhereBegin(pParse, pSrc, pWhere, 0,0,WHERE_ONEPASS_DESIRED,0); + pWInfo = sqlite4WhereBegin(pParse, pSrc, pWhere, 0, 0, WHERE_ONEPASS_DESIRED); if( pWInfo==0 ) goto update_cleanup; - okOnePass = sqlite4WhereOkOnePass(pWInfo); + okOnePass = pWInfo->okOnePass; sqlite4VdbeAddOp2(v, OP_RowKey, iCur+iPk, regOldKey); if( !okOnePass ){ sqlite4VdbeAddOp3(v, OP_RowSetAdd, regRowSet, 0, regOldKey); } sqlite4WhereEnd(pWInfo); Index: src/utf.c ================================================================== --- src/utf.c +++ src/utf.c @@ -579,11 +579,11 @@ if( n<0 ){ u8 *z = (u8*)p; while( z[0] || z[1] ) z += 2; n = z - (u8*)p; } - nReq = n * 2 + 2; + nReq = n * 2 + 1; }else{ /* When converting from UTF-16, the maximum growth results from ** translating a 2-byte character to a 4-byte UTF-8 character. ** A single byte is required for the output string ** nul-terminator. */ Index: src/util.c ================================================================== --- src/util.c +++ src/util.c @@ -378,10 +378,407 @@ int sqlite4Atoi(const char *z){ int x = 0; if( z ) sqlite4GetInt32(z, &x); return x; } + +/* +** The variable-length integer encoding is as follows: +** +** KEY: +** A = 0xxxxxxx 7 bits of data and one flag bit +** B = 1xxxxxxx 7 bits of data and one flag bit +** C = xxxxxxxx 8 bits of data +** +** 7 bits - A +** 14 bits - BA +** 21 bits - BBA +** 28 bits - BBBA +** 35 bits - BBBBA +** 42 bits - BBBBBA +** 49 bits - BBBBBBA +** 56 bits - BBBBBBBA +** 64 bits - BBBBBBBBC +*/ + +/* +** Write a 64-bit variable-length integer to memory starting at p[0]. +** The length of data write will be between 1 and 9 bytes. The number +** of bytes written is returned. +** +** A variable-length integer consists of the lower 7 bits of each byte +** for all bytes that have the 8th bit set and one byte with the 8th +** bit clear. Except, if we get to the 9th byte, it stores the full +** 8 bits and is the last byte. +*/ +int sqlite4PutVarint(unsigned char *p, u64 v){ + int i, j, n; + u8 buf[10]; + if( v & (((u64)0xff000000)<<32) ){ + p[8] = (u8)v; + v >>= 8; + for(i=7; i>=0; i--){ + p[i] = (u8)((v & 0x7f) | 0x80); + v >>= 7; + } + return 9; + } + n = 0; + do{ + buf[n++] = (u8)((v & 0x7f) | 0x80); + v >>= 7; + }while( v!=0 ); + buf[0] &= 0x7f; + assert( n<=9 ); + for(i=0, j=n-1; j>=0; j--, i++){ + p[i] = buf[j]; + } + return n; +} + +/* +** This routine is a faster version of sqlite4PutVarint() that only +** works for 32-bit positive integers and which is optimized for +** the common case of small integers. A MACRO version, putVarint32, +** is provided which inlines the single-byte case. All code should use +** the MACRO version as this function assumes the single-byte case has +** already been handled. +*/ +int sqlite4PutVarint32(unsigned char *p, u32 v){ +#ifndef putVarint32 + if( (v & ~0x7f)==0 ){ + p[0] = v; + return 1; + } +#endif + if( (v & ~0x3fff)==0 ){ + p[0] = (u8)((v>>7) | 0x80); + p[1] = (u8)(v & 0x7f); + return 2; + } + return sqlite4PutVarint(p, v); +} + +/* +** Bitmasks used by sqlite4GetVarint(). These precomputed constants +** are defined here rather than simply putting the constant expressions +** inline in order to work around bugs in the RVT compiler. +** +** SLOT_2_0 A mask for (0x7f<<14) | 0x7f +** +** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0 +*/ +#define SLOT_2_0 0x001fc07f +#define SLOT_4_2_0 0xf01fc07f + + +/* +** Read a 64-bit variable-length integer from memory starting at p[0]. +** Return the number of bytes read. The value is stored in *v. +*/ +u8 sqlite4GetVarint(const unsigned char *p, u64 *v){ + u32 a,b,s; + + a = *p; + /* a: p0 (unmasked) */ + if (!(a&0x80)) + { + *v = a; + return 1; + } + + p++; + b = *p; + /* b: p1 (unmasked) */ + if (!(b&0x80)) + { + a &= 0x7f; + a = a<<7; + a |= b; + *v = a; + return 2; + } + + /* Verify that constants are precomputed correctly */ + assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) ); + assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) ); + + p++; + a = a<<14; + a |= *p; + /* a: p0<<14 | p2 (unmasked) */ + if (!(a&0x80)) + { + a &= SLOT_2_0; + b &= 0x7f; + b = b<<7; + a |= b; + *v = a; + return 3; + } + + /* CSE1 from below */ + a &= SLOT_2_0; + p++; + b = b<<14; + b |= *p; + /* b: p1<<14 | p3 (unmasked) */ + if (!(b&0x80)) + { + b &= SLOT_2_0; + /* moved CSE1 up */ + /* a &= (0x7f<<14)|(0x7f); */ + a = a<<7; + a |= b; + *v = a; + return 4; + } + + /* a: p0<<14 | p2 (masked) */ + /* b: p1<<14 | p3 (unmasked) */ + /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ + /* moved CSE1 up */ + /* a &= (0x7f<<14)|(0x7f); */ + b &= SLOT_2_0; + s = a; + /* s: p0<<14 | p2 (masked) */ + + p++; + a = a<<14; + a |= *p; + /* a: p0<<28 | p2<<14 | p4 (unmasked) */ + if (!(a&0x80)) + { + /* we can skip these cause they were (effectively) done above in calc'ing s */ + /* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */ + /* b &= (0x7f<<14)|(0x7f); */ + b = b<<7; + a |= b; + s = s>>18; + *v = ((u64)s)<<32 | a; + return 5; + } + + /* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ + s = s<<7; + s |= b; + /* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ + + p++; + b = b<<14; + b |= *p; + /* b: p1<<28 | p3<<14 | p5 (unmasked) */ + if (!(b&0x80)) + { + /* we can skip this cause it was (effectively) done above in calc'ing s */ + /* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */ + a &= SLOT_2_0; + a = a<<7; + a |= b; + s = s>>18; + *v = ((u64)s)<<32 | a; + return 6; + } + + p++; + a = a<<14; + a |= *p; + /* a: p2<<28 | p4<<14 | p6 (unmasked) */ + if (!(a&0x80)) + { + a &= SLOT_4_2_0; + b &= SLOT_2_0; + b = b<<7; + a |= b; + s = s>>11; + *v = ((u64)s)<<32 | a; + return 7; + } + + /* CSE2 from below */ + a &= SLOT_2_0; + p++; + b = b<<14; + b |= *p; + /* b: p3<<28 | p5<<14 | p7 (unmasked) */ + if (!(b&0x80)) + { + b &= SLOT_4_2_0; + /* moved CSE2 up */ + /* a &= (0x7f<<14)|(0x7f); */ + a = a<<7; + a |= b; + s = s>>4; + *v = ((u64)s)<<32 | a; + return 8; + } + + p++; + a = a<<15; + a |= *p; + /* a: p4<<29 | p6<<15 | p8 (unmasked) */ + + /* moved CSE2 up */ + /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */ + b &= SLOT_2_0; + b = b<<8; + a |= b; + + s = s<<4; + b = p[-4]; + b &= 0x7f; + b = b>>3; + s |= b; + + *v = ((u64)s)<<32 | a; + + return 9; +} + +/* +** Read a 32-bit variable-length integer from memory starting at p[0]. +** Return the number of bytes read. The value is stored in *v. +** +** If the varint stored in p[0] is larger than can fit in a 32-bit unsigned +** integer, then set *v to 0xffffffff. +** +** A MACRO version, getVarint32, is provided which inlines the +** single-byte case. All code should use the MACRO version as +** this function assumes the single-byte case has already been handled. +*/ +u8 sqlite4GetVarint32(const unsigned char *p, u32 *v){ + u32 a,b; + + /* The 1-byte case. Overwhelmingly the most common. Handled inline + ** by the getVarin32() macro */ + a = *p; + /* a: p0 (unmasked) */ +#ifndef getVarint32 + if (!(a&0x80)) + { + /* Values between 0 and 127 */ + *v = a; + return 1; + } +#endif + + /* The 2-byte case */ + p++; + b = *p; + /* b: p1 (unmasked) */ + if (!(b&0x80)) + { + /* Values between 128 and 16383 */ + a &= 0x7f; + a = a<<7; + *v = a | b; + return 2; + } + + /* The 3-byte case */ + p++; + a = a<<14; + a |= *p; + /* a: p0<<14 | p2 (unmasked) */ + if (!(a&0x80)) + { + /* Values between 16384 and 2097151 */ + a &= (0x7f<<14)|(0x7f); + b &= 0x7f; + b = b<<7; + *v = a | b; + return 3; + } + + /* A 32-bit varint is used to store size information in btrees. + ** Objects are rarely larger than 2MiB limit of a 3-byte varint. + ** A 3-byte varint is sufficient, for example, to record the size + ** of a 1048569-byte BLOB or string. + ** + ** We only unroll the first 1-, 2-, and 3- byte cases. The very + ** rare larger cases can be handled by the slower 64-bit varint + ** routine. + */ +#if 1 + { + u64 v64; + u8 n; + + p -= 2; + n = sqlite4GetVarint(p, &v64); + assert( n>3 && n<=9 ); + if( (v64 & SQLITE4_MAX_U32)!=v64 ){ + *v = 0xffffffff; + }else{ + *v = (u32)v64; + } + return n; + } + +#else + /* For following code (kept for historical record only) shows an + ** unrolling for the 3- and 4-byte varint cases. This code is + ** slightly faster, but it is also larger and much harder to test. + */ + p++; + b = b<<14; + b |= *p; + /* b: p1<<14 | p3 (unmasked) */ + if (!(b&0x80)) + { + /* Values between 2097152 and 268435455 */ + b &= (0x7f<<14)|(0x7f); + a &= (0x7f<<14)|(0x7f); + a = a<<7; + *v = a | b; + return 4; + } + + p++; + a = a<<14; + a |= *p; + /* a: p0<<28 | p2<<14 | p4 (unmasked) */ + if (!(a&0x80)) + { + /* Values between 268435456 and 34359738367 */ + a &= SLOT_4_2_0; + b &= SLOT_4_2_0; + b = b<<7; + *v = a | b; + return 5; + } + + /* We can only reach this point when reading a corrupt database + ** file. In that case we are not in any hurry. Use the (relatively + ** slow) general-purpose sqlite4GetVarint() routine to extract the + ** value. */ + { + u64 v64; + u8 n; + + p -= 4; + n = sqlite4GetVarint(p, &v64); + assert( n>5 && n<=9 ); + *v = (u32)v64; + return n; + } +#endif +} + +/* +** Return the number of bytes that will be needed to store the given +** 64-bit integer. +*/ +int sqlite4VarintLen(u64 v){ + int i = 0; + do{ + i++; + v >>= 7; + }while( v!=0 && ALWAYS(i<9) ); + return i; +} + /* ** Read or write a four-byte big-endian integer value. */ u32 sqlite4Get4byte(const u8 *p){ Index: src/varint.c ================================================================== --- src/varint.c +++ src/varint.c @@ -222,38 +222,10 @@ varintWrite32(z+1, w); varintWrite32(z+5, y); return 9; } -/* -** Return the number of bytes required to encode value v as a varint. -*/ -int sqlite4VarintLen(sqlite4_uint64 v){ - unsigned char aDummy[9]; - return sqlite4PutVarint64(aDummy, v); -} - -/* -** Read a varint from buffer z and set *pResult to the value read. -** Return the number of bytes read from the buffer. -*/ -int sqlite4GetVarint32(const unsigned char *z, u32 *pResult){ - sqlite4_uint64 iRes; - int ret; - ret = sqlite4GetVarint64(z, 9, &iRes); - *pResult = (u32)iRes; - return ret; -} - -/* -** Encode v as a varint and write the result to buffer p. Return the -** number of bytes written. -*/ -int sqlite4PutVarint32(unsigned char *p, u32 v){ - return sqlite4PutVarint64(p, v); -} - /* ** Compile this one file with the -DTEST_VARINT option to run the simple ** test case below. The test program generates 10 million random 64-bit ** values, weighted toward smaller numbers, and for each value it encodes ** and then decodes the varint to verify that the same number comes back. Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -208,21 +208,18 @@ ROUND8(sizeof(VdbeCursor)) + 2*nField*sizeof(u32); assert( iCurnCursor ); if( p->apCsr[iCur] ){ - sqlite4VdbeFreeCursor(p->apCsr[iCur]); + sqlite4VdbeFreeCursor(p, p->apCsr[iCur]); p->apCsr[iCur] = 0; } if( SQLITE4_OK==sqlite4VdbeMemGrow(pMem, nByte, 0) ){ p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z; memset(pCx, 0, sizeof(VdbeCursor)); - pCx->db = p->db; pCx->iDb = iDb; pCx->nField = nField; - pCx->rowChnged = 1; - sqlite4_buffer_init(&pCx->sSeekKey, p->db->pEnv->pMM); } return pCx; } /* @@ -852,11 +849,10 @@ ** ** The 32-bit integer value P1 is written into register P2. */ case OP_Integer: { /* out2-prerelease */ pOut->u.num = sqlite4_num_from_int64((i64)pOp->p1); - MemSetTypeFlag(pOut, MEM_Int); break; } /* Opcode: Num P1 P2 * P4 * ** @@ -1260,11 +1256,10 @@ pOut->u.num = sqlite4_num_div(num2, num1); break; default: { iA = sqlite4_num_to_int64(num1, 0); iB = sqlite4_num_to_int64(num2, 0); if( iA==0 ) goto arithmetic_result_is_null; - if( iA==-1 ) iA = 1; pOut->u.num = sqlite4_num_from_int64(iB % iA); break; } } @@ -1821,15 +1816,14 @@ pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (flags1&MEM_TypeMask); pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (flags3&MEM_TypeMask); break; } -/* Opcode: Permutation P1 * * P4 * +/* Opcode: Permutation * * * P4 * ** ** Set the permutation used by the OP_Compare operator to be the array -** of integers in P4. P4 will contain exactly P1 elements. The P1 -** parameter is used only for printing the P4 array when debugging. +** of integers in P4. ** ** The permutation is only valid until the next OP_Permutation, OP_Compare, ** OP_Halt, or OP_ResultRow. Typically the OP_Permutation should occur ** immediately prior to the OP_Compare. */ @@ -2099,41 +2093,64 @@ ** then the cache of the cursor is reset prior to extracting the column. ** The first OP_Column against a pseudo-table after the value of the content ** register has changed should have this bit set. */ case OP_Column: { + KVCursor *pKVCur; /* Cursor for current entry in the KV storage */ + ValueDecoder *pCodec; /* The decoder object */ int p1; /* Index of VdbeCursor to decode */ - int mxField; /* Maximum column number */ VdbeCursor *pC; /* The VDBE cursor */ Mem *pDest; /* Where to write the results */ + const KVByteArray *aData; /* The content to be decoded */ + KVSize nData; /* Size of aData[] in bytes */ Mem *pDefault; /* Default value from P4 */ + Mem *pReg; /* */ p1 = pOp->p1; assert( p1nCursor ); assert( pOp->p3>0 && pOp->p3<=p->nMem ); pDest = &aMem[pOp->p3]; memAboutToChange(p, pDest); pC = p->apCsr[p1]; assert( pC!=0 ); - assert( pC->iRoot!=KVSTORE_ROOT ); #ifndef SQLITE4_OMIT_VIRTUALTABLE assert( pC->pVtabCursor==0 ); #endif - if( pC->pDecoder==0 ){ - mxField = pC->nField; - if( pC->pKeyInfo && pC->pKeyInfo->nData ) mxField = pC->pKeyInfo->nData; - rc = sqlite4VdbeDecoderCreate(db, pC, 0, mxField, &pC->pDecoder); - pC->rowChnged = 1; - } - if( rc==SQLITE4_OK ){ - pDefault = (pOp->p4type==P4_MEM) ? pOp->p4.pMem : 0; - rc = sqlite4VdbeDecoderGetColumn(pC->pDecoder, pOp->p2, pDefault, pDest); + pKVCur = pC->pKVCur; + if( pKVCur!=0 ){ + if( pC->nullRow ){ + aData = 0; + }else{ + rc = sqlite4KVCursorData(pKVCur, 0, -1, &aData, &nData); + } + }else if( ALWAYS(pC->pseudoTableReg>0) ){ + pReg = &aMem[pC->pseudoTableReg]; + assert( pReg->flags & MEM_Blob ); + assert( memIsValid(pReg) ); + aData = (const KVByteArray*)pReg->z; + nData = pReg->n; + }else{ + aData = 0; + MemSetTypeFlag(pDest, MEM_Null); + } + if( rc==SQLITE4_OK && aData ){ + /* TODO: Fix this somehow... */ + int nField = pC->nField; + if( pC->pKeyInfo && pC->pKeyInfo->nData ) nField = pC->pKeyInfo->nData; + + rc = sqlite4VdbeCreateDecoder(db, aData, nData, nField, &pCodec); + if( rc==0 ){ + pDefault = (pOp->p4type==P4_MEM) ? pOp->p4.pMem : 0; + rc = sqlite4VdbeDecodeValue(pCodec, pOp->p2, pDefault, pDest); + sqlite4VdbeDestroyDecoder(pCodec); + } }else{ sqlite4VdbeMemSetNull(pDest); } UPDATE_MAX_BLOBSIZE(pDest); REGISTER_TRACE(pOp->p3, pDest); + assert( rc<100 ); break; } /* Opcode: Affinity P1 P2 * P4 * ** @@ -2164,20 +2181,22 @@ /* Opcode: MakeIdxKey P1 P2 P3 P4 P5 ** ** P1 is an open cursor. P2 is the first register in a contiguous array ** of N registers containing values to encode into a database key. Normally, -** N is taken from the KeyInfo object of P1. However, of P4 is a positive -** integer, P4 is used for N instead. +** N is equal to the number of columns indexed by P1, plus the number of +** trailing primary key columns (if any). +** +** Or, if P4 is a non-zero integer, then it contains the value for N. ** ** This instruction encodes the N values into a database key and writes ** the result to register P3. No affinity transformations are applied to ** the input values before they are encoded. ** ** If the OPFLAG_SEQCOUNT bit of P5 is set, then a sequence number ** (unique within the cursor) is appended to the record. The sole purpose -** of this is to ensure that the key blob is unique within the cursor table. +** of this is to ensure that the key blob is unique within the cursors table. ** ** If the OPFLAG_PARTIALKEY bit of P5 is set, that means the value supplied ** for N is not the true number of values in the key, only the number that ** need to be encoded for this operation. This effects the encoding of ** final BLOBs. @@ -2197,15 +2216,13 @@ pKeyInfo = pC->pKeyInfo; pData0 = &aMem[pOp->p2]; pOut = &aMem[pOp->p3]; aRec = 0; - /* If P4 contains OPFLAG_SEQCOUNT, encode the sequence number blob to be - ** appended to the end of the key. Variable nSeq is set to the number - ** of bytes in the encoded key. A non-standard encoding is used (not - ** the usual varint encoding) so that the OP_GrpCompare opcode can easily - ** back up over the sequence count to find the true end of the key. + /* If pOp->p5 is non-zero, encode the sequence number blob to append to + ** the end of the key. Variable nSeq is set to the number of bytes in + ** the encoded key. */ nSeq = 0; if( pOp->p5 & OPFLAG_SEQCOUNT ){ iSeq = pC->seqCount++; do { @@ -2216,18 +2233,17 @@ aSeq[sizeof(aSeq)-nSeq] |= 0x80; } memAboutToChange(p, pOut); - if( pOp->p4type==P4_INT32 && pOp->p4.i>0 ){ + nField = pKeyInfo->nField; + if( pOp->p4type==P4_INT32 && pOp->p4.i ){ nField = pOp->p4.i; assert( nField<=pKeyInfo->nField ); - }else{ - nField = pKeyInfo->nField; } rc = sqlite4VdbeEncodeKey( - db, pData0, nField, pKeyInfo->nField, + db, pData0, nField, nField+(pOp->p5 & OPFLAG_PARTIALKEY), pC->iRoot, pKeyInfo, &aRec, &nRec, nSeq ); if( rc ){ sqlite4DbFree(db, aRec); @@ -2258,18 +2274,13 @@ ** character of the string indicates the column affinity that should be used ** for the nth field of the index key. The mapping from character to affinity ** is given by the SQLITE4_AFF_ macros defined in sqliteInt.h. If P4 is NULL ** then all index fields have the affinity NONE. ** -** If this instruction is immediately preceded by OP_Permutation, then the -** specified permutation is used to determine the order that registers are -** used to build the record. The i-th column of the record is taken from -** register P1+aPermute[i]. If OP_Permutation has not been run, then the i-th -** column comes from register P1+i. -** -** This opcode applies the affinities that it specifies to the input -** array elements. Then, if P3 is not 0, it encodes the input array +** This opcode expands any zero-blobs within the input array. Then if +** P4 is not NULL it applies the affinities that it specifies to the input +** array elements. Finally, if P3 is not 0, it encodes the input array ** into a data record and stores the result in register P3. The OP_Column ** opcode can be used to decode the record. ** ** Specifying P3==0 is only useful if the previous opcode is an OP_MakeKey. */ @@ -2284,14 +2295,10 @@ Mem *pKeyOut; /* Where to store the generated key */ int keyReg; /* Register into which to write the key */ u8 *aRec; /* The constructed key or value */ int nRec; /* Size of aRec[] in bytes */ - assert( aPermute==0 || pOp->opcode!=OP_MakeKey ); - assert( aPermute==0 || pOp->p4type==P4_NOTUSED ); - assert( aPermute==0 || pOp->p3 ); - if( pOp->opcode==OP_MakeKey ){ pC = p->apCsr[pOp->p1]; keyReg = pOp->p2; pKeyOut = &aMem[keyReg]; memAboutToChange(p, pKeyOut); @@ -2304,13 +2311,14 @@ if( p->trace ) sqlite4VdbePrintOp(p->trace, pc, pOp); #endif }else{ pC = 0; } + nField = pOp->p1; zAffinity = pOp->p4.z; - assert( pOp->p1>0 && pOp->p2>0 && pOp->p2+pOp->p1<=p->nMem+1 ); - pData0 = &aMem[pOp->p1]; + assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=p->nMem+1 ); + pData0 = &aMem[nField]; nField = pOp->p2; pLast = &pData0[nField-1]; /* Loop through the input elements. Apply affinity to each one and ** expand all zero-blobs. @@ -2337,26 +2345,25 @@ REGISTER_TRACE(keyReg, pKeyOut); UPDATE_MAX_BLOBSIZE(pKeyOut); } } - /* If P3 is not 0, compute the data record */ + /* If P3 is not 0, compute the data rescord */ if( rc==SQLITE4_OK && pOp->p3 ){ assert( pOp->p3p1 || pOp->p3>=pOp->p1+pOp->p2 ); pOut = &aMem[pOp->p3]; memAboutToChange(p, pOut); aRec = 0; - rc = sqlite4VdbeEncodeData(db, pData0, aPermute, nField, &aRec, &nRec); + rc = sqlite4VdbeEncodeData(db, pData0, nField, &aRec, &nRec); if( rc ){ sqlite4DbFree(db, aRec); }else{ rc = sqlite4VdbeMemSetStr(pOut, (char *)aRec, nRec, 0, SQLITE4_DYNAMIC,0); REGISTER_TRACE(pOp->p3, pOut); UPDATE_MAX_BLOBSIZE(pOut); } } - aPermute = 0; break; } /* Opcode: Count P1 P2 * * * ** @@ -2535,30 +2542,10 @@ } } break; } -/* Opcode: ReadCookie P1 P2 * * * -** -** Read the schema cookie from database P1 and write it into register P2. -** -** There must be a read-lock on the database (either a transaction -** must be started or there must be an open cursor) before -** executing this instruction. -*/ -case OP_ReadCookie: { /* out2-prerelease */ - unsigned int iMeta; - KVStore *pKV; - - assert( pOp->p1>=0 && pOp->p1nDb ); - pKV = db->aDb[pOp->p1].pKV; - rc = sqlite4KVStoreGetSchema(pKV, &iMeta); - pOut->u.num = sqlite4_num_from_int64(iMeta); - MemSetTypeFlag(pOut, MEM_Int); - break; -} - /* Opcode: SetCookie P1 P2 P3 * * ** ** Write the content of register P3 (interpreted as an integer) ** into cookie number P2 of database P1. P2==1 is the schema version. ** P2==2 is the database format. P2==3 is the recommended pager cache @@ -2735,21 +2722,30 @@ goto abort_due_to_error; } } if( pOp->p4type==P4_KEYINFO ){ pKeyInfo = pOp->p4.pKeyInfo; + pKeyInfo->enc = ENC(p->db); nField = pKeyInfo->nField+1; }else if( pOp->p4type==P4_INT32 ){ nField = pOp->p4.i; } assert( pOp->p1>=0 ); pCur = allocateCursor(p, pOp->p1, nField, iDb, 1); if( pCur==0 ) goto no_mem; pCur->nullRow = 1; + pCur->isOrdered = 1; pCur->iRoot = p2; rc = sqlite4KVStoreOpenCursor(pX, &pCur->pKVCur); pCur->pKeyInfo = pKeyInfo; + + /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of + ** SQLite used to check if the root-page flags were sane at this point + ** and report database corruption if they were not, but this check has + ** since moved into the btree layer. */ + pCur->isTable = pOp->p4type!=P4_KEYINFO; + pCur->isIndex = !pCur->isTable; break; } /* Opcode: OpenEphemeral P1 P2 * P4 P5 ** @@ -2795,11 +2791,14 @@ ); if( rc==SQLITE4_OK ) rc = sqlite4KVStoreOpenCursor(pCx->pTmpKV, &pCx->pKVCur); if( rc==SQLITE4_OK ) rc = sqlite4KVStoreBegin(pCx->pTmpKV, 2); pCx->pKeyInfo = pOp->p4.pKeyInfo; + if( pCx->pKeyInfo ) pCx->pKeyInfo->enc = ENC(p->db); + pCx->isIndex = !pCx->isTable; + pCx->isOrdered = 1; break; } /* Opcode: OpenSorter P1 P2 * P4 * ** @@ -2811,19 +2810,47 @@ /* VdbeCursor *pCx; */ pOp->opcode = OP_OpenEphemeral; pc--; break; } + +/* Opcode: OpenPseudo P1 P2 P3 * * +** +** Open a new cursor that points to a fake table that contains a single +** row of data. The content of that one row is the content of memory +** register P2. In other words, cursor P1 becomes an alias for the +** MEM_Blob content contained in register P2. +** +** A pseudo-table created by this opcode is used to hold a single +** row output from the sorter so that the row can be decomposed into +** individual columns using the OP_Column opcode. The OP_Column opcode +** is the only cursor opcode that works with a pseudo-table. +** +** P3 is the number of fields in the records that will be stored by +** the pseudo-table. +*/ +case OP_OpenPseudo: { + VdbeCursor *pCx; + + assert( pOp->p1>=0 ); + pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0); + if( pCx==0 ) goto no_mem; + pCx->nullRow = 1; + pCx->pseudoTableReg = pOp->p2; + pCx->isTable = 1; + pCx->isIndex = 0; + break; +} /* Opcode: Close P1 * * * * ** ** Close a cursor previously opened as P1. If P1 is not ** currently open, this instruction is a no-op. */ case OP_Close: { assert( pOp->p1>=0 && pOp->p1nCursor ); - sqlite4VdbeFreeCursor(p->apCsr[pOp->p1]); + sqlite4VdbeFreeCursor(p, p->apCsr[pOp->p1]); p->apCsr[pOp->p1] = 0; break; } /* Opcode: SeekPk P1 * P3 * * @@ -2832,99 +2859,109 @@ ** on an auxiliary index on the same table. P3 must be pointing to a valid ** index entry. ** ** This opcode seeks cursor P1 so that it points to the PK index entry ** that corresponds to the same table row as the current entry that -** cursor P3 points to. The entry must exist. -** -** Actually, the seek is deferred until it is actually needed and if the -** PRIMARY KEY index is never referenced, the seek never takes place. The -** sqlite3VdbeCursorMoveto() does the seek, if necessary. If the target -** row does not exist in the PRIMARY KEY table, then the -** sqlite3VdbeCursorMoveto() routine will throw an SQLITE4_CORRUPT error. +** cursor P3 points to. The entry must exist. If it does not, this opcode +** throws an SQLITE4_CORRUPT exception. */ case OP_SeekPk: { - KVByteArray *aKey; /* Key data from cursor pIdx */ - KVSize nKey; /* Size of aKey[] in bytes */ VdbeCursor *pPk; /* Cursor P1 */ VdbeCursor *pIdx; /* Cursor P3 */ + KVByteArray const *aKey; /* Key data from cursor pIdx */ + KVSize nKey; /* Size of aKey[] in bytes */ int nShort; /* Size of aKey[] without PK fields */ - int nVarint; /* Size of varint pPk->iRoot */ + KVByteArray *aPkKey; + KVSize nPkKey; pPk = p->apCsr[pOp->p1]; pIdx = p->apCsr[pOp->p3]; if( pIdx->pFts ){ - rc = sqlite4Fts5Pk(pIdx->pFts, pPk->iRoot, &aKey, &nKey); + rc = sqlite4Fts5Pk(pIdx->pFts, pPk->iRoot, &aPkKey, &nPkKey); if( rc==SQLITE4_OK ){ - rc = sqlite4KVCursorSeek(pPk->pKVCur, aKey, nKey, 0); + rc = sqlite4KVCursorSeek(pPk->pKVCur, aPkKey, nPkKey, 0); if( rc==SQLITE4_NOTFOUND ) rc = SQLITE4_CORRUPT_BKPT; pPk->nullRow = 0; } }else{ - rc = sqlite4KVCursorKey(pIdx->pKVCur, (const KVByteArray **)&aKey, &nKey); - if( rc!=SQLITE4_OK ) break; - nShort = sqlite4VdbeShortKey(aKey, nKey, - pIdx->pKeyInfo->nField - pIdx->pKeyInfo->nPK, 0 - ); - nVarint = sqlite4VarintLen(pPk->iRoot); - rc = sqlite4_buffer_resize(&pPk->sSeekKey, nVarint + nKey - nShort); - if( rc!=SQLITE4_OK ) break; - putVarint32((u8 *)(pPk->sSeekKey.p), pPk->iRoot); - memcpy(((u8*)pPk->sSeekKey.p) + nVarint, &aKey[nShort], nKey-nShort); - assert( pPk->sSeekKey.n>0 ); - } - pPk->rowChnged = 1; + assert( pIdx->pKeyInfo->nPK>0 ); + assert( pPk->pKeyInfo->nPK==0 ); + rc = sqlite4KVCursorKey(pIdx->pKVCur, &aKey, &nKey); + if( rc==SQLITE4_OK ){ + nShort = sqlite4VdbeShortKey(aKey, nKey, + pIdx->pKeyInfo->nField - pIdx->pKeyInfo->nPK, 0 + ); + + nPkKey = sqlite4VarintLen(pPk->iRoot) + nKey - nShort; + aPkKey = sqlite4DbMallocRaw(db, nPkKey); + + if( aPkKey ){ + putVarint32(aPkKey, pPk->iRoot); + memcpy(&aPkKey[nPkKey - (nKey-nShort)], &aKey[nShort], nKey-nShort); + rc = sqlite4KVCursorSeek(pPk->pKVCur, aPkKey, nPkKey, 0); + if( rc==SQLITE4_NOTFOUND ){ + rc = SQLITE4_CORRUPT_BKPT; + } + pPk->nullRow = 0; + sqlite4DbFree(db, aPkKey); + } + } + } break; } /* Opcode: SeekGe P1 P2 P3 P4 * ** -** P1 identifies an open database cursor. The cursor is repositioned so -** that it points to the smallest entry in its index that is greater than -** or equal to the key formed by the array of P4 registers starting at -** register P3. +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the value in register P3 as the key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. ** -** If there are no records greater than or equal to the key and P2 is -** not zero, then jump to P2. +** Reposition cursor P1 so that it points to the smallest entry that +** is greater than or equal to the key value. If there are no records +** greater than or equal to the key and P2 is not zero, then jump to P2. ** ** See also: Found, NotFound, Distinct, SeekLt, SeekGt, SeekLe */ /* Opcode: SeekGt P1 P2 P3 P4 * ** -** P1 identifies an open database cursor. The cursor is repositioned so -** that it points to the smallest entry in its index that is greater than -** the key formed by the array of P4 registers starting at -** register P3. +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. ** -** If there are no records greater than the key and P2 is -** not zero, then jump to P2. +** Reposition cursor P1 so that it points to the smallest entry that +** is greater than the key value. If there are no records greater than +** the key and P2 is not zero, then jump to P2. ** ** See also: Found, NotFound, Distinct, SeekLt, SeekGe, SeekLe */ /* Opcode: SeekLt P1 P2 P3 P4 * ** -** P1 identifies an open database cursor. The cursor is repositioned so -** that it points to the largest entry in its index that is less than -** the key formed by the array of P4 registers starting at -** register P3. +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. ** -** If there are no records less than the key and P2 is -** not zero, then jump to P2. +** Reposition cursor P1 so that it points to the largest entry that +** is less than the key value. If there are no records less than +** the key and P2 is not zero, then jump to P2. ** ** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLe */ /* Opcode: SeekLe P1 P2 P3 P4 * ** -** P1 identifies an open database cursor. The cursor is repositioned so -** that it points to the largest entry in its index that is less than or -** equal to the key formed by the array of P4 registers starting at -** register P3. +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. ** -** If there are no records less than or equal to the key and P2 is -** not zero, then jump to P2. +** Reposition cursor P1 so that it points to the largest entry that +** is less than or equal to the key value. If there are no records +** less than or equal to the key and P2 is not zero, then jump to P2. ** ** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt */ case OP_SeekLt: /* jump, in3 */ case OP_SeekLe: /* jump, in3 */ @@ -2939,51 +2976,43 @@ const KVByteArray *aKey; /* Pointer to final cursor key */ KVSize nKey; /* Size of aKey[] in bytes */ pC = p->apCsr[pOp->p1]; pC->nullRow = 0; - pC->sSeekKey.n = 0; - pC->rowChnged = 1; assert( pOp->p1>=0 && pOp->p1nCursor ); assert( pOp->p2!=0 ); assert( pC!=0 ); + assert( pC->pseudoTableReg==0 ); assert( OP_SeekLe == OP_SeekLt+1 ); assert( OP_SeekGe == OP_SeekLt+2 ); assert( OP_SeekGt == OP_SeekLt+3 ); - - dir = +1; - op = pOp->opcode; - if( op==OP_SeekLe || op==OP_SeekLt ) dir = -1; + assert( pC->isOrdered ); /* Encode a database key consisting of the contents of the P4 registers ** starting at register P3. Have the vdbecodec module allocate an extra ** free byte at the end of the database key (see below). */ + op = pOp->opcode; nField = pOp->p4.i; pIn3 = &aMem[pOp->p3]; - if( pC->iRoot!=KVSTORE_ROOT ){ - rc = sqlite4VdbeEncodeKey( - db, pIn3, nField, nField+(pOp->p5 & OPFLAG_PARTIALKEY), - pC->iRoot, pC->pKeyInfo, &aProbe, &nProbe, 1 - ); - - /* Opcode search-dir increment-key - ** -------------------------------------- - ** SeekLt -1 no - ** SeekLe -1 yes - ** SeekGe +1 no - ** SeekGt +1 yes - */ - if( op==OP_SeekLe || op==OP_SeekGt ) aProbe[nProbe++] = 0xFF; - if( rc==SQLITE4_OK ){ - rc = sqlite4KVCursorSeek(pC->pKVCur, aProbe, nProbe, dir); - } - }else{ - Stringify(pIn3, encoding); - rc = sqlite4KVCursorSeek( - pC->pKVCur, (const KVByteArray *)pIn3->z, pIn3->n, dir - ); + rc = sqlite4VdbeEncodeKey( + db, pIn3, nField, nField+(pOp->p5 & OPFLAG_PARTIALKEY), + pC->iRoot, pC->pKeyInfo, &aProbe, &nProbe, 1 + ); + + /* Opcode search-dir increment-key + ** -------------------------------------- + ** SeekLt -1 no + ** SeekLe -1 yes + ** SeekGe +1 no + ** SeekGt +1 yes + */ + dir = +1; + if( op==OP_SeekLe || op==OP_SeekLt ) dir = -1; + if( op==OP_SeekLe || op==OP_SeekGt ) aProbe[nProbe++] = 0xFF; + if( rc==SQLITE4_OK ){ + rc = sqlite4KVCursorSeek(pC->pKVCur, aProbe, nProbe, dir); } if( rc==SQLITE4_OK ){ if( op==OP_SeekLt ){ rc = sqlite4KVCursorPrev(pC->pKVCur); @@ -2990,28 +3019,23 @@ }else if( op==OP_SeekGt ){ rc = sqlite4KVCursorNext(pC->pKVCur); } } - if( pC->iRoot!=KVSTORE_ROOT ){ - /* Check that the KV cursor currently points to an entry belonging - ** to index pC->iRoot (and not an entry that is part of some other - ** index). */ - if( rc==SQLITE4_OK || rc==SQLITE4_INEXACT ){ - rc = sqlite4KVCursorKey(pC->pKVCur, &aKey, &nKey); - if( rc==SQLITE4_OK && memcmp(aKey, aProbe, sqlite4VarintLen(pC->iRoot)) ){ - rc = SQLITE4_NOTFOUND; - } - } - - /* Free the key allocated above. If no error has occurred but the cursor - ** does not currently point to a valid entry, jump to instruction P2. */ - sqlite4DbFree(db, aProbe); - }else if( rc==SQLITE4_INEXACT ){ - rc = SQLITE4_OK; - } - + /* Check that the KV cursor currently points to an entry belonging + ** to index pC->iRoot (and not an entry that is part of some other + ** index). */ + if( rc==SQLITE4_OK || rc==SQLITE4_INEXACT ){ + rc = sqlite4KVCursorKey(pC->pKVCur, &aKey, &nKey); + if( rc==SQLITE4_OK && memcmp(aKey, aProbe, sqlite4VarintLen(pC->iRoot)) ){ + rc = SQLITE4_NOTFOUND; + } + } + + /* Free the key allocated above. If no error has occurred but the cursor + ** does not currently point to a valid entry, jump to instruction P2. */ + sqlite4DbFree(db, aProbe); if( rc==SQLITE4_NOTFOUND ){ rc = SQLITE4_OK; pc = pOp->p2 - 1; } break; @@ -3028,12 +3052,12 @@ KVByteArray *aKey; KVSize nKey; assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; - pC->rowChnged = 1; assert( pC!=0 ); + assert( pC->isTable ); pKVCur = pC->pKVCur; rc = sqlite4VdbeEncodeKey(db, aMem+pOp->p2, 1, 1, pC->iRoot, 0, &aKey, &nKey, 0); if( rc==SQLITE4_OK ){ rc = sqlite4KVCursorSeek(pKVCur, aKey, nKey, 0); @@ -3103,15 +3127,14 @@ alreadyExists = 0; assert( pOp->p1>=0 && pOp->p1nCursor ); assert( pOp->p4type==P4_INT32 ); pC = p->apCsr[pOp->p1]; - pC->sSeekKey.n = 0; - pC->rowChnged = 1; assert( pC!=0 ); pIn3 = &aMem[pOp->p3]; assert( pC->pKVCur!=0 ); + assert( pC->isTable==0 || pOp->opcode==OP_NotExists ); if( pOp->p4.i>0 ){ rc = sqlite4VdbeEncodeKey( db, pIn3, pOp->p4.i, pOp->p4.i + (pOp->p5 & OPFLAG_PARTIALKEY), pC->iRoot, pC->pKeyInfo, &pProbe, &nProbe, 0 ); @@ -3172,11 +3195,10 @@ assert( pOp->p4type==P4_INT32 ); pProbe = &aMem[pOp->p3]; pC = p->apCsr[pOp->p1]; - pC->rowChnged = 1; pOut = (pOp->p4.i==0 ? 0 : &aMem[pOp->p4.i]); assert( pOut==0 || (pOut->flags & MEM_Blob) ); nShort = sqlite4VdbeShortKey((u8 *)pProbe->z, pProbe->n, pC->pKeyInfo->nField - pC->pKeyInfo->nPK, 0 @@ -3241,11 +3263,10 @@ VdbeCursor *pC; /* Cursor of table to get the new rowid */ const KVByteArray *aKey; /* Key of an existing row */ KVSize nKey; /* Size of the existing row key */ int n; /* Number of bytes decoded */ i64 i3; /* Integer value from pIn3 */ - sqlite4_num vNum; /* Intermediate result */ v = 0; assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); @@ -3280,12 +3301,12 @@ n = sqlite4GetVarint64((u8 *)aKey, nKey, (u64 *)&v); if( n==0 ) rc = SQLITE4_CORRUPT_BKPT; if( v!=pC->iRoot ) rc = SQLITE4_CORRUPT_BKPT; } if( rc==SQLITE4_OK ){ - n = sqlite4VdbeDecodeNumericKey(&aKey[n], nKey-n, &vNum); - if( n==0 || (v = sqlite4_num_to_int64(vNum,0))==LARGEST_INT64 ){ + n = sqlite4VdbeDecodeIntKey(&aKey[n], nKey-n, &v); + if( n==0 || v==LARGEST_INT64 ){ assert( 0 ); rc = SQLITE4_FULL; } } }else{ @@ -3357,10 +3378,88 @@ } pIn1->u.num = sqlite4_num_from_int64(i1); break; } + +/* Opcode: Insert P1 P2 P3 P4 P5 +** +** 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 MEM_Blob stored in register +** number P2. The key is stored in register P3. The key must +** be a MEM_Int. +** +** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is +** incremented (otherwise not). If the OPFLAG_LASTROWID flag of P5 is set, +** then rowid is stored for subsequent return by the +** sqlite4_last_insert_rowid() function (otherwise it is unmodified). +** +** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an +** UPDATE operation. Otherwise (if the flag is clear) then this opcode +** is part of an INSERT operation. The difference is only important to +** the update hook. +** +** Parameter P4 may point to a string containing the table-name, or +** may be NULL. If it is not NULL, then the update-hook +** (sqlite4.xUpdateCallback) is invoked following a successful insert. +** +** (WARNING/TODO: If P1 is a pseudo-cursor and P2 is dynamically +** allocated, then ownership of P2 is transferred to the pseudo-cursor +** and register P2 becomes ephemeral. If the cursor is changed, the +** value of register P2 will then change. Make sure this does not +** cause any problems.) +** +** This instruction only works on tables. The equivalent instruction +** for indices is OP_IdxInsert. +*/ +/* Opcode: InsertInt P1 P2 P3 P4 P5 +** +** This works exactly like OP_Insert except that the key is the +** integer value P3, not the value of the integer stored in register P3. +*/ +case OP_Insert: +case OP_InsertInt: { + Mem *pData; /* MEM cell holding data for the record to be inserted */ + Mem *pKey; /* MEM cell holding key for the record */ + i64 iKey; /* The integer ROWID or key for the record to be inserted */ + VdbeCursor *pC; /* Cursor to table into which insert is written */ + int n; + KVByteArray aKey[24]; + + pData = &aMem[pOp->p2]; + assert( pOp->p1>=0 && pOp->p1nCursor ); + assert( memIsValid(pData) ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + REGISTER_TRACE(pOp->p2, pData); + + if( pOp->opcode==OP_Insert ){ + pKey = &aMem[pOp->p3]; + assert( pKey->flags & MEM_Int ); + assert( memIsValid(pKey) ); + REGISTER_TRACE(pOp->p3, pKey); + iKey = sqlite4_num_to_int64(pKey->u.num, 0); + }else{ + /* assert( pOp->opcode==OP_InsertInt ); */ + iKey = pOp->p3; + } + + if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; + if( pData->flags & MEM_Null ){ + pData->z = 0; + pData->n = 0; + }else{ + assert( pData->flags & (MEM_Blob|MEM_Str) ); + } + n = sqlite4PutVarint64(aKey, pC->iRoot); + n += sqlite4VdbeEncodeIntKey(&aKey[n], iKey); + rc = sqlite4KVStoreReplace(pC->pKVCur->pStore, aKey, n, + (const KVByteArray*)pData->z, pData->n); + + break; +} /* Opcode: Delete P1 P2 * * * ** ** Delete the record at which the P1 cursor is currently pointing. ** @@ -3377,12 +3476,10 @@ case OP_Delete: { VdbeCursor *pC; assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); - assert( pC->sSeekKey.n==0 ); - pC->rowChnged = 1; rc = sqlite4KVCursorDelete(pC->pKVCur); if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; break; } @@ -3480,13 +3577,13 @@ memAboutToChange(p, pOut); /* Note that RowKey and RowData are really exactly the same instruction */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; - rc = sqlite4VdbeCursorMoveto(pC); - if( rc!=SQLITE4_OK ) break; + assert( pC!=0 ); assert( pC->nullRow==0 ); + assert( pC->pseudoTableReg==0 ); assert( pC->pKVCur!=0 ); pCrsr = pC->pKVCur; if( pOp->opcode==OP_RowKey ){ rc = sqlite4KVCursorKey(pCrsr, &pData, &nData); @@ -3538,10 +3635,11 @@ aIncr = &aMem[pOp->p3]; nTotal = pOp->p4.i; pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->nullRow==0 ); + assert( pC->pseudoTableReg==0 ); assert( pC->pKVCur!=0 ); assert( pOp->p4type==P4_INT32 ); rc = sqlite4KVCursorKey(pC->pKVCur, &pNew, &nNew); if( rc==SQLITE4_OK ){ @@ -3589,17 +3687,15 @@ VdbeCursor *pC; i64 v; const KVByteArray *aKey; KVSize nKey; int n; - sqlite4_num vNum; assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; - rc = sqlite4VdbeCursorMoveto(pC); - if( rc!=SQLITE4_OK ) break; - assert( pC->sSeekKey.n==0 ); + assert( pC!=0 ); + assert( pC->pseudoTableReg==0 ); if( pC->nullRow ){ pOut->flags = MEM_Null; break; #ifndef SQLITE4_OMIT_VIRTUALTABLE }else if( pC->pVtabCursor ){ @@ -3611,13 +3707,12 @@ #endif /* SQLITE4_OMIT_VIRTUALTABLE */ }else{ rc = sqlite4KVCursorKey(pC->pKVCur, &aKey, &nKey); if( rc==SQLITE4_OK ){ n = sqlite4GetVarint64(aKey, nKey, (sqlite4_uint64*)&v); - n = sqlite4VdbeDecodeNumericKey(&aKey[n], nKey-n, &vNum); + n = sqlite4VdbeDecodeIntKey(&aKey[n], nKey-n, &v); if( n==0 ) rc = SQLITE4_CORRUPT; - v = sqlite4_num_to_int64(vNum,0); } } pOut->u.num = sqlite4_num_from_int64(v); break; } @@ -3633,11 +3728,10 @@ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); pC->nullRow = 1; - pC->rowChnged = 1; break; } /* Opcode: Last P1 P2 * * * ** @@ -3778,58 +3872,43 @@ } break; } -/* Opcode: Insert P1 P2 P3 * P5 +/* Opcode: SorterInsert P1 P2 P3 +*/ +/* Opcode: IdxInsert P1 P2 P3 * P5 ** ** Register P3 holds the key and register P2 holds the data for an ** index entry. Write this record into the index specified by the ** cursor P1. ** -** P3 can be either an integer or a blob. If it is a blob then its value -** is used as-is as the KVStore key. If P3 is an integer, then the KVStore -** key is constructed using P3 as the INTEGER PRIMARY KEY value. -** ** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is ** incremented (otherwise not). */ -case OP_Insert: { +case OP_SorterInsert: +case OP_IdxInsert: { VdbeCursor *pC; Mem *pKey; Mem *pData; - int nKVKey; - KVByteArray *pKVKey; - KVByteArray aKey[24]; - pC = p->apCsr[pOp->p1]; pKey = &aMem[pOp->p3]; pData = pOp->p2 ? &aMem[pOp->p2] : 0; assert( pOp->p1>=0 && pOp->p1nCursor ); assert( pC && pC->pKVCur && pC->pKVCur->pStore ); + assert( pKey->flags & MEM_Blob ); assert( pData==0 || (pData->flags & MEM_Blob) ); if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; - - if( pKey->flags & MEM_Int ){ - nKVKey = sqlite4PutVarint64(aKey, pC->iRoot); - nKVKey += sqlite4VdbeEncodeIntKey(aKey+nKVKey, sqlite4VdbeIntValue(pKey)); - pKVKey = aKey; - }else{ - nKVKey = pKey->n; - pKVKey = pKey->z; - } - rc = sqlite4KVStoreReplace( pC->pKVCur->pStore, - (u8 *)pKVKey, nKVKey, + (u8 *)pKey->z, pKey->n, (u8 *)(pData ? pData->z : 0), (pData ? pData->n : 0) ); - pC->rowChnged = 1; break; } /* Opcode: IdxDelete P1 * P3 * * @@ -3852,62 +3931,24 @@ if( rc==SQLITE4_OK ){ rc = sqlite4KVCursorDelete(pC->pKVCur); }else if( rc==SQLITE4_NOTFOUND ){ rc = SQLITE4_OK; } - pC->rowChnged = 1; break; } -/* Opcode: IdxRowkey P1 P2 P3 * * -** -** Cursor P1 points to an index entry. Extract the encoded primary key -** fields from the entry. Then set output register P2 to a blob value -** containing the value P3 as a varint followed by the encoded PK -** fields. -** -** See also: Rowkey +/* Opcode: IdxRowid P1 P2 * * * +** +** Write into register P2 an integer which is the last entry in the record at +** the end of the index key pointed to by cursor P1. This integer should be +** the rowid of the table entry to which this index entry points. +** +** See also: Rowid, MakeRecord. */ -case OP_IdxRowkey: { /* out2-prerelease */ - KVByteArray const *aKey; /* Key data from cursor pIdx */ - KVSize nKey; /* Size of aKey[] in bytes */ - int nShort; /* Size of aKey[] without PK fields */ - KVByteArray *aPkKey; /* Pointer to PK buffer */ - KVSize nPkKey; /* Size of aPkKey in bytes */ - int iRoot; - VdbeCursor *pC; - - iRoot = pOp->p3; - pOut = &aMem[pOp->p2]; - memAboutToChange(p, pOut); - - pC = p->apCsr[pOp->p1]; - - rc = sqlite4KVCursorKey(pC->pKVCur, &aKey, &nKey); - if( rc!=SQLITE4_OK ) break; - - nShort = sqlite4VdbeShortKey(aKey, nKey, - pC->pKeyInfo->nField - pC->pKeyInfo->nPK, 0 - ); - - nPkKey = sqlite4VarintLen(iRoot) + nKey - nShort; - if( nPkKey>db->aLimit[SQLITE4_LIMIT_LENGTH] ){ - goto too_big; - } - - rc = sqlite4VdbeMemGrow(pOut, nPkKey, 0); - if( rc!=SQLITE4_OK ) break; - aPkKey = pOut->z; - putVarint32(aPkKey, iRoot); - memcpy(&aPkKey[nPkKey - (nKey-nShort)], &aKey[nShort], nKey-nShort); - pOut->type = SQLITE4_BLOB; - pOut->n = nPkKey; - MemSetTypeFlag(pOut, MEM_Blob); - - pOut->enc = SQLITE4_UTF8; /* In case the blob is ever cast to text */ - UPDATE_MAX_BLOBSIZE(pOut); +case OP_IdxRowid: { /* out2-prerelease */ + assert( 0 ); break; } /* Opcode: IdxGE P1 P2 P3 ** Index: src/vdbe.h ================================================================== --- src/vdbe.h +++ src/vdbe.h @@ -50,21 +50,23 @@ int p3; /* The third parameter */ union { /* fourth parameter */ int i; /* Integer value if p4type==P4_INT32 */ void *p; /* Generic pointer */ char *z; /* Pointer to data for string (char array) types */ - sqlite4_num *pNum; /* Used when p4type is P4_NUM */ + i64 *pI64; /* Used when p4type is P4_INT64 */ + double *pReal; /* Used when p4type is P4_REAL */ FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */ VdbeFunc *pVdbeFunc; /* Used when p4type is P4_VDBEFUNC */ CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */ Mem *pMem; /* Used when p4type is P4_MEM */ VTable *pVtab; /* Used when p4type is P4_VTAB */ KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */ int *ai; /* Used when p4type is P4_INTARRAY */ SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */ Fts5Info *pFtsInfo; /* Used when p4type is P4_FTS5INDEXINFO */ - int (*xAdvance)(VdbeCursor*); /* Used with p4type==P4_ADVANCE */ + int (*xAdvance)(VdbeCursor*); + sqlite4_num *pNum; /* Used when p4type is P4_NUM */ } p4; #ifdef SQLITE4_DEBUG char *zComment; /* Comment to improve readability */ #endif #ifdef VDBE_PROFILE @@ -99,40 +101,41 @@ signed char p3; /* Third parameter */ }; typedef struct VdbeOpList VdbeOpList; /* -** Allowed values of VdbeOp.p4type. All values are less than 1 so that -** they can be used unambiguously in the "length" parameter of various -** interfaces. +** Allowed values of VdbeOp.p4type */ -#define P4_NOTUSED 0 /* The P4 parameter is not used */ -#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */ -#define P4_DYNAMIC (-1) /* Pointer to a string obtained from malloc() */ -#define P4_STATIC (-2) /* Pointer to a static string */ -#define P4_COLLSEQ (-3) /* P4 is a pointer to a CollSeq structure */ -#define P4_FUNCDEF (-4) /* P4 is a pointer to a FuncDef structure */ -#define P4_KEYINFO (-5) /* P4 is a pointer to a KeyInfo structure */ -#define P4_VDBEFUNC (-6) /* P4 is a pointer to a VdbeFunc structure */ -#define P4_MEM (-7) /* P4 is a pointer to a Mem* structure */ -#define P4_VTAB (-8) /* P4 is a pointer to an sqlite4_vtab structure */ -#define P4_NUM (-9) /* P4 is a pointer to an sqlite4_num structure */ -#define P4_INT32 (-10) /* P4 is a 32-bit signed integer */ -#define P4_INTARRAY (-11) /* P4 is a vector of 32-bit integers */ -#define P4_SUBPROGRAM (-12) /* P4 is a pointer to a SubProgram structure */ -#define P4_ADVANCE (-13) /* P4 is a pointer to BtreeNext() or BtreePrev() */ -#define P4_FTS5INFO (-14) /* P4 points to an Fts5Info structure */ +#define P4_NOTUSED 0 /* The P4 parameter is not used */ +#define P4_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */ +#define P4_STATIC (-2) /* Pointer to a static string */ +#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */ +#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */ +#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */ +#define P4_VDBEFUNC (-7) /* P4 is a pointer to a VdbeFunc structure */ +#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */ +#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */ +#define P4_VTAB (-10) /* P4 is a pointer to an sqlite4_vtab structure */ +#define P4_MPRINTF (-11) /* P4 is a string obtained from sqlite4_mprintf() */ +#define P4_REAL (-12) /* P4 is a 64-bit floating point value */ +#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ +#define P4_INT32 (-14) /* P4 is a 32-bit signed integer */ +#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ +#define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */ +#define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */ +#define P4_FTS5INFO (-20) /* P4 points to an Fts5Info structure */ +#define P4_NUM (-21) /* P4 points to an Fts5Info structure */ /* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure ** is made. That copy is freed when the Vdbe is finalized. But if the ** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used. It still ** gets freed when the Vdbe is finalized so it still should be obtained ** from a single sqliteMalloc(). But no copy is made and the calling ** function should *not* try to free the KeyInfo. */ -#define P4_KEYINFO_HANDOFF (-124) -#define P4_KEYINFO_STATIC (-125) +#define P4_KEYINFO_HANDOFF (-16) +#define P4_KEYINFO_STATIC (-17) /* ** The Vdbe.aColName array contains 5n Mem structures, where n is the ** number of columns of data returned by the statement. */ @@ -214,10 +217,13 @@ #ifndef SQLITE4_OMIT_TRACE char *sqlite4VdbeExpandSql(Vdbe*, const char*); #endif sqlite4_value *sqlite4ColumnValue(sqlite4_stmt *pStmt, int iCol); +void sqlite4VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); +UnpackedRecord *sqlite4VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); + #ifndef SQLITE4_OMIT_TRIGGER void sqlite4VdbeLinkSubProgram(Vdbe *, SubProgram *); #endif Index: src/vdbeInt.h ================================================================== --- src/vdbeInt.h +++ src/vdbeInt.h @@ -35,11 +35,11 @@ /* Opaque type used by the explainer */ typedef struct Explain Explain; /* Opaque type used by vdbecodec.c */ -typedef struct RowDecoder RowDecoder; +typedef struct ValueDecoder ValueDecoder; /* ** A cursor is a pointer into a single database. ** The cursor can seek to an entry with a particular key, or ** loop over all entries. You can also insert new @@ -48,35 +48,34 @@ ** ** Every cursor that the virtual machine has open is represented by an ** instance of the following structure. */ struct VdbeCursor { - sqlite4 *db; /* The connection that owns this cursor */ - KVCursor *pKVCur; /* The cursor structure of the storage engine */ + KVCursor *pKVCur; /* The cursor structure of the backend */ KVStore *pTmpKV; /* Separate file holding a temporary table */ KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ int iDb; /* Index of cursor database in db->aDb[] (or -1) */ int iRoot; /* Root page of the table */ + int pseudoTableReg; /* Register holding pseudotable content. */ int nField; /* Number of fields in the header */ + Bool zeroed; /* True if zeroed out and ready for reuse */ + Bool atFirst; /* True if pointing to first entry */ Bool nullRow; /* True if pointing to a row with no data */ - Bool rowChnged; /* True if row has changed out from under pDecoder */ - i64 seqCount; /* Sequence counter */ - VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */ - Fts5Cursor *pFts; /* Fts5 cursor object (or NULL) */ - RowDecoder *pDecoder; /* Decoder for row content */ + Bool isTable; /* True if a table requiring integer keys */ + Bool isIndex; /* True if an index containing keys only - no data */ + Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */ sqlite4_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */ const sqlite4_module *pModule; /* Module for cursor pVtabCursor */ - sqlite4_buffer sSeekKey; /* Key for deferred seek */ -}; - -/* Methods for the VdbeCursor object */ -void sqlite4VdbeFreeCursor(VdbeCursor*); -int sqlite4VdbeSeekEnd(VdbeCursor*, int); -int sqlite4VdbeNext(VdbeCursor*); -int sqlite4VdbePrevious(VdbeCursor*); -int sqlite4VdbeCursorMoveto(VdbeCursor *); - + i64 seqCount; /* Sequence counter */ + i64 movetoTarget; /* Argument to the deferred move-to */ + VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */ + Fts5Cursor *pFts; /* Fts5 cursor object (or NULL) */ + + /* Result of last sqlite4-Moveto() done by an OP_NotExists or + ** OP_IsUnique opcode on this cursor. */ + int seekResult; +}; /* ** When a sub-program is executed (OP_Program), a structure of this type ** is allocated to store the current value of the program counter, as ** well as the current memory cell array and various other frame specific @@ -169,10 +168,11 @@ #define MEM_Blob 0x0010 /* Value is a BLOB */ #define MEM_RowSet 0x0020 /* Value is a RowSet object */ #define MEM_Frame 0x0040 /* Value is a VdbeFrame object */ #define MEM_Invalid 0x0080 /* Value is undefined */ #define MEM_TypeMask 0x00ff /* Mask of type bits */ + /* Whenever Mem contains a valid string or blob representation, one of ** the following flags must be set to determine the memory management ** policy for Mem.z. The MEM_Term flag tells us whether or not the ** string is \000 or \u0000 terminated @@ -337,34 +337,38 @@ #define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */ /* ** Function prototypes */ +void sqlite4VdbeFreeCursor(Vdbe *, VdbeCursor*); void sqliteVdbePopStack(Vdbe*,int); #if defined(SQLITE4_DEBUG) || defined(VDBE_PROFILE) void sqlite4VdbePrintOp(FILE*, int, Op*); #endif +u32 sqlite4VdbeSerialTypeLen(u32); +u32 sqlite4VdbeSerialType(Mem*, int); +u32 sqlite4VdbeSerialPut(unsigned char*, int, Mem*, int); +u32 sqlite4VdbeSerialGet(const unsigned char*, u32, Mem*); void sqlite4VdbeDeleteAuxData(VdbeFunc*, int); -int sqlite4VdbeDecoderCreate( +int sqlite4VdbeCreateDecoder( sqlite4 *db, /* The database connection */ - VdbeCursor *pCur, /* Cursor associated with this decoder */ - KVCursor *pKVCur, /* Alternative cursor if pCur is NULL */ + const unsigned char *aIn, /* The input data blob */ + int nIn, /* Number of bytes in aIn[] */ int mxCol, /* Maximum number of columns in aIn[] */ - RowDecoder **ppOut /* The newly generated decoder object */ + ValueDecoder **ppOut /* The newly generated decoder object */ ); -int sqlite4VdbeDecoderDestroy(RowDecoder *pDecoder); -int sqlite4VdbeDecoderGetColumn( - RowDecoder *pDecoder, /* The decoder for the whole string */ +int sqlite4VdbeDestroyDecoder(ValueDecoder *pDecoder); +int sqlite4VdbeDecodeValue( + ValueDecoder *pDecoder, /* The decoder for the whole string */ int iVal, /* Index of the value to decode. First is 0 */ Mem *pDefault, /* The default value. Often NULL */ Mem *pOut /* Write the result here */ ); int sqlite4VdbeEncodeData( sqlite4 *db, /* The database connection */ Mem *aIn, /* Array of values to encode */ - int *aPermute, /* Permutation (or NULL) */ int nIn, /* Number of entries in aIn[] */ u8 **pzOut, /* The output data record */ int *pnOut /* Bytes of content in pzOut */ ); int sqlite4VdbeEncodeKey( @@ -377,11 +381,11 @@ u8 **pzOut, /* Write the resulting key here */ int *pnOut, /* Number of bytes in the key */ int nExtra /* Append extra bytes on end of key */ ); int sqlite4VdbeEncodeIntKey(u8 *aBuf,sqlite4_int64 v); -int sqlite4VdbeDecodeNumericKey(const KVByteArray*, KVSize, sqlite4_num*); +int sqlite4VdbeDecodeIntKey(const KVByteArray*, KVSize, sqlite4_int64*); int sqlite4VdbeShortKey(const u8 *, int, int, int *); int sqlite4MemCompare(Mem*, Mem*, const CollSeq*,int*); int sqlite4VdbeExec(Vdbe*); int sqlite4VdbeList(Vdbe*); int sqlite4VdbeHalt(Vdbe*); @@ -422,10 +426,14 @@ int sqlite4VdbeCloseStatement(Vdbe *, int); void sqlite4VdbeFrameDelete(VdbeFrame*); int sqlite4VdbeFrameRestore(VdbeFrame *); void sqlite4VdbeMemStoreType(Mem *pMem); int sqlite4VdbeTransferError(Vdbe *p); +int sqlite4VdbeSeekEnd(VdbeCursor*, int); +int sqlite4VdbeNext(VdbeCursor*); +int sqlite4VdbePrevious(VdbeCursor*); + int sqlite4VdbeRollback(sqlite4 *db, int iLevel); int sqlite4VdbeCommit(sqlite4 *db, int iLevel); #ifdef SQLITE4_DEBUG void sqlite4VdbeMemAboutToChange(Vdbe*,Mem*); Index: src/vdbeapi.c ================================================================== --- src/vdbeapi.c +++ src/vdbeapi.c @@ -147,27 +147,27 @@ sqlite4_int64 sqlite4_value_int64(sqlite4_value *pVal){ return sqlite4VdbeIntValue((Mem*)pVal); } const char *sqlite4_value_text(sqlite4_value *pVal, int *pnByte){ const char *zRet = (const char *)sqlite4ValueText(pVal, SQLITE4_UTF8); - if( pnByte ) *pnByte = (zRet ? ((Mem *)pVal)->n : 0); + if( pnByte ) *pnByte = ((Mem *)pVal)->n; return zRet; } #ifndef SQLITE4_OMIT_UTF16 const void *sqlite4_value_text16(sqlite4_value* pVal, int *pnByte){ const void *pRet = sqlite4ValueText(pVal, SQLITE4_UTF16NATIVE); - if( pnByte ) *pnByte = (pRet ? ((Mem *)pVal)->n : 0); + if( pnByte ) *pnByte = ((Mem *)pVal)->n; return pRet; } const void *sqlite4_value_text16be(sqlite4_value *pVal, int *pnByte){ const void *pRet = sqlite4ValueText(pVal, SQLITE4_UTF16BE); - if( pnByte ) *pnByte = (pRet ? ((Mem *)pVal)->n : 0); + if( pnByte ) *pnByte = ((Mem *)pVal)->n; return pRet; } const void *sqlite4_value_text16le(sqlite4_value *pVal, int *pnByte){ const void *pRet = sqlite4ValueText(pVal, SQLITE4_UTF16LE); - if( pnByte ) *pnByte = (pRet ? ((Mem *)pVal)->n : 0); + if( pnByte ) *pnByte = ((Mem *)pVal)->n; return pRet; } #endif /* SQLITE4_OMIT_UTF16 */ int sqlite4_value_type(sqlite4_value* pVal){ return pVal->type; Index: src/vdbeaux.c ================================================================== --- src/vdbeaux.c +++ src/vdbeaux.c @@ -582,17 +582,23 @@ */ static void freeP4(sqlite4 *db, int p4type, void *p4){ if( p4 ){ assert( db ); switch( p4type ){ + case P4_REAL: case P4_NUM: + case P4_INT64: case P4_DYNAMIC: case P4_KEYINFO: case P4_INTARRAY: case P4_KEYINFO_HANDOFF: { sqlite4DbFree(db, p4); break; + } + case P4_MPRINTF: { + if( db->pnBytesFreed==0 ) sqlite4_free(db->pEnv, p4); + break; } case P4_VDBEFUNC: { VdbeFunc *pVdbeFunc = (VdbeFunc *)p4; freeEphemeralFunction(db, pVdbeFunc->pFunc); if( db->pnBytesFreed==0 ) sqlite4VdbeDeleteAuxData(pVdbeFunc, 0); @@ -839,19 +845,17 @@ ** Compute a string that describes the P4 parameter for an opcode. ** Use zTemp for any required temporary buffer space. */ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ char *zP4 = zTemp; - assert( nTemp>=30 ); + assert( nTemp>=20 ); switch( pOp->p4type ){ case P4_KEYINFO_STATIC: case P4_KEYINFO: { int i, j; KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; - i = sqlite4_snprintf(zTemp, nTemp, - "keyinfo(%d,%d,%d", pKeyInfo->nField, pKeyInfo->nPK, - pKeyInfo->nData); + i = sqlite4_snprintf(zTemp, nTemp, "keyinfo(%d", pKeyInfo->nField); for(j=0; jnField; j++){ CollSeq *pColl = pKeyInfo->aColl[j]; if( pColl ){ int n = sqlite4Strlen30(pColl->zName); if( i+n>nTemp-6 ){ @@ -881,17 +885,21 @@ } case P4_FUNCDEF: { FuncDef *pDef = pOp->p4.pFunc; sqlite4_snprintf(zTemp, nTemp, "%s(%d)", pDef->zName, pDef->nArg); break; + } + case P4_INT64: { + sqlite4_snprintf(zTemp, nTemp, "%lld", *pOp->p4.pI64); + break; } case P4_INT32: { sqlite4_snprintf(zTemp, nTemp, "%d", pOp->p4.i); break; } - case P4_NUM: { - sqlite4_num_to_text(*pOp->p4.pNum, zTemp, 0); + case P4_REAL: { + sqlite4_snprintf(zTemp, nTemp, "%.16g", *pOp->p4.pReal); break; } case P4_MEM: { Mem *pMem = pOp->p4.pMem; if( pMem->flags & MEM_Str ){ @@ -914,18 +922,11 @@ sqlite4_snprintf(zTemp, nTemp, "vtab:%p:%p", pVtab, pVtab->pModule); break; } #endif case P4_INTARRAY: { - int i, j, n, cSep = '('; - i = sqlite4_snprintf(zTemp, nTemp, "intarray"); - n = pOp->opcode==OP_Permutation ? pOp->p1 : 0; - for(j=0; jp4.ai[j]); - cSep = ','; - } - sqlite4_snprintf(zTemp+i, nTemp-i, ")"); + sqlite4_snprintf(zTemp, nTemp, "intarray"); break; } case P4_SUBPROGRAM: { sqlite4_snprintf(zTemp, nTemp, "program"); break; @@ -933,24 +934,14 @@ case P4_ADVANCE: { zTemp[0] = 0; break; } default: { - if( pOp->opcode==OP_Blob ){ - int n = pOp->p1*2+2; - if( n>nTemp-2 ) n = nTemp-2; - zTemp[0] = 'x'; - zTemp[1] = '\''; - sqlite4BlobToHex((n-2)/2,pOp->p4.z,zTemp+2); - zTemp[n] = '\''; - zTemp[n+1] = 0; - }else{ - zP4 = pOp->p4.z; - if( zP4==0 ){ - zP4 = zTemp; - zTemp[0] = 0; - } + zP4 = pOp->p4.z; + if( zP4==0 ){ + zP4 = zTemp; + zTemp[0] = 0; } } } assert( zP4!=0 ); return zP4; @@ -969,11 +960,11 @@ /* ** Print a single opcode. This routine is used for debugging only. */ void sqlite4VdbePrintOp(FILE *pOut, int pc, Op *pOp){ char *zP4; - char zPtr[150]; + char zPtr[50]; static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-4s %.2X %s\n"; if( pOut==0 ) pOut = stdout; zP4 = displayP4(pOp, zPtr, sizeof(zPtr)); fprintf(pOut, zFormat1, pc, sqlite4OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5, @@ -1036,11 +1027,11 @@ void sqlite4VdbeFrameDelete(VdbeFrame *p){ int i; Mem *aMem = VdbeFrameMem(p); VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem]; for(i=0; inChildCsr; i++){ - sqlite4VdbeFreeCursor(apCsr[i]); + sqlite4VdbeFreeCursor(p->v, apCsr[i]); } releaseMemArray(aMem, p->nChildMem); sqlite4DbFree(p->v->db, p); } @@ -1190,16 +1181,16 @@ pMem->flags = MEM_Int; pMem->u.num = sqlite4_num_from_int64(pOp->p3); /* P3 */ pMem->type = SQLITE4_INTEGER; pMem++; - if( sqlite4VdbeMemGrow(pMem, 150, 0) ){ /* P4 */ + if( sqlite4VdbeMemGrow(pMem, 32, 0) ){ /* P4 */ assert( p->db->mallocFailed ); return SQLITE4_ERROR; } pMem->flags = MEM_Dyn|MEM_Str|MEM_Term; - z = displayP4(pOp, pMem->z, 150); + z = displayP4(pOp, pMem->z, 32); if( z!=pMem->z ){ sqlite4VdbeMemSetStr(pMem, z, -1, SQLITE4_UTF8, 0, 0); }else{ assert( pMem->z!=0 ); pMem->n = sqlite4Strlen30(pMem->z); @@ -1493,10 +1484,36 @@ } } p->explain = pParse->explain; sqlite4VdbeRewind(p); } + +/* +** Close a VDBE cursor and release all the resources that cursor +** happens to hold. +*/ +void sqlite4VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){ + if( pCx==0 ){ + return; + } + sqlite4Fts5Close(pCx->pFts); + if( pCx->pKVCur ){ + sqlite4KVCursorClose(pCx->pKVCur); + } + if( pCx->pTmpKV ){ + sqlite4KVStoreClose(pCx->pTmpKV); + } +#ifndef SQLITE4_OMIT_VIRTUALTABLE + if( pCx->pVtabCursor ){ + sqlite4_vtab_cursor *pVtabCursor = pCx->pVtabCursor; + const sqlite4_module *pModule = pCx->pModule; + p->inVtabMethod = 1; + pModule->xClose(pVtabCursor); + p->inVtabMethod = 0; + } +#endif +} /* ** Copy the values stored in the VdbeFrame structure to its Vdbe. This ** is used, for example, when a trigger sub-program is halted to restore ** control to the main program. @@ -1535,11 +1552,11 @@ if( p->apCsr ){ int i; for(i=0; inCursor; i++){ VdbeCursor *pC = p->apCsr[i]; if( pC ){ - sqlite4VdbeFreeCursor(pC); + sqlite4VdbeFreeCursor(p, pC); p->apCsr[i] = 0; } } } if( p->aMem ){ @@ -2176,10 +2193,56 @@ # define swapMixedEndianFloat(X) X = floatSwap(X) #else # define swapMixedEndianFloat(X) #endif + +/* +** This routine is used to allocate sufficient space for an UnpackedRecord +** structure large enough to be used with sqlite4VdbeRecordUnpack() if +** the first argument is a pointer to KeyInfo structure pKeyInfo. +** +** The space is either allocated using sqlite4DbMallocRaw() or from within +** the unaligned buffer passed via the second and third arguments (presumably +** stack space). If the former, then *ppFree is set to a pointer that should +** be eventually freed by the caller using sqlite4DbFree(). Or, if the +** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL +** before returning. +** +** If an OOM error occurs, NULL is returned. +*/ +UnpackedRecord *sqlite4VdbeAllocUnpackedRecord( + KeyInfo *pKeyInfo, /* Description of the record */ + char *pSpace, /* Unaligned space available */ + int szSpace, /* Size of pSpace[] in bytes */ + char **ppFree /* OUT: Caller should free this pointer */ +){ + UnpackedRecord *p; /* Unpacked record to return */ + int nOff; /* Increment pSpace by nOff to align it */ + int nByte; /* Number of bytes required for *p */ + + /* We want to shift the pointer pSpace up such that it is 8-byte aligned. + ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift + ** it by. If pSpace is already 8-byte aligned, nOff should be zero. + */ + nOff = (8 - (SQLITE4_PTR_TO_INT(pSpace) & 7)) & 7; + nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1); + if( nByte>szSpace+nOff ){ + p = (UnpackedRecord *)sqlite4DbMallocRaw(pKeyInfo->db, nByte); + *ppFree = (char *)p; + if( !p ) return 0; + }else{ + p = (UnpackedRecord*)&pSpace[nOff]; + *ppFree = 0; + } + + p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))]; + p->pKeyInfo = pKeyInfo; + p->nField = pKeyInfo->nField + 1; + return p; +} + /* ** This routine sets the value to be returned by subsequent calls to ** sqlite4_changes() on the database handle 'db'. */ Index: src/vdbecodec.c ================================================================== --- src/vdbecodec.c +++ src/vdbecodec.c @@ -16,413 +16,58 @@ #include "sqliteInt.h" #include "vdbeInt.h" /* ** The decoder object. -** -** An instance of this object is used to extract individual columns (numbers, -** strings, blobs, or NULLs) from a row of a table or index. Usually the -** content is extract from the value side of the key/value pair, though -** sometimes information might be taken from the key as well. -** -** When the VDBE needs to extract multiple columns from the same row, it will -** try to reuse a single decoder object. The decoder, therefore, should attempt -** to cache any intermediate results that might be useful on later invocations. */ -struct RowDecoder { +struct ValueDecoder { sqlite4 *db; /* The database connection */ - VdbeCursor *pCur; /* The cursor for being decoded */ - KVCursor *pKVCur; /* Alternative KVCursor if pCur is NULL */ - const KVByteArray *a; /* Content to be decoded */ - const KVByteArray *aKey; /* Key content */ - KVSize n; /* Bytes of content in a[] */ - KVSize nKey; /* Bytes of key content */ + const u8 *a; /* Content to be decoded */ + int n; /* Bytes of content in a[] */ int mxCol; /* Maximum number of columns */ }; /* ** Create an object that can be used to decode fields of the data encoding. ** ** The aIn[] value must remain stable for the life of the decoder. */ -int sqlite4VdbeDecoderCreate( +int sqlite4VdbeCreateDecoder( sqlite4 *db, /* The database connection */ - VdbeCursor *pCur, /* The cursor associated with this decoder */ - KVCursor *pKVCur, /* Alternative KVCursor */ - int mxCol, /* Maximum number of columns to ever decode */ - RowDecoder **ppOut /* Return the answer here */ + const unsigned char *aIn, /* The input data blob */ + int nIn, /* Number of bytes in aIn[] */ + int mxCol, /* Maximum number of columns in aIn[] */ + ValueDecoder **ppOut /* The newly generated decoder object */ ){ - RowDecoder *p; + ValueDecoder *p; - assert( pCur==0 || pKVCur==0 ); - assert( pCur!=0 || pKVCur!=0 ); p = sqlite4DbMallocZero(db, sizeof(*p)); *ppOut = p; if( p==0 ) return SQLITE4_NOMEM; p->db = db; - p->pCur = pCur; - p->pKVCur = pKVCur; + p->a = aIn; + p->n = nIn; p->mxCol = mxCol; return SQLITE4_OK; } /* ** Destroy a decoder object previously created ** using sqlite4VdbeCreateDecoder(). */ -int sqlite4VdbeDecoderDestroy(RowDecoder *p){ +int sqlite4VdbeDestroyDecoder(ValueDecoder *p){ if( p ){ sqlite4DbFree(p->db, p); } return SQLITE4_OK; } /* -** Make sure the p->a and p->n fields are valid and current. -*/ -static int decoderFetchData(RowDecoder *p){ - VdbeCursor *pCur = p->pCur; - int rc; - if( pCur==0 ){ - rc = sqlite4KVCursorData(p->pKVCur, 0, -1, &p->a, &p->n); - return rc; - } - if( pCur->rowChnged ){ - p->a = 0; - p->aKey = 0; - pCur->rowChnged = 0; - } - if( p->a ) return SQLITE4_OK; - rc = sqlite4VdbeCursorMoveto(pCur); - if( rc ) return rc; - if( pCur->nullRow ){ - p->a = 0; - p->n = 0; - return SQLITE4_OK; - } - assert( pCur->pKVCur!=0 ); - return sqlite4KVCursorData(pCur->pKVCur, 0, -1, &p->a, &p->n); -} - -/* -** Make sure the p->aKey and p->nKey fields are valid and current. -*/ -static int decoderFetchKey(RowDecoder *p){ - VdbeCursor *pCur = p->pCur; - int rc; - if( pCur==0 ){ - rc = sqlite4KVCursorKey(p->pKVCur, &p->aKey, &p->nKey); - return rc; - } - assert( p->a!=0 ); - if( p->aKey ) return SQLITE4_OK; - assert( pCur->pKVCur!=0 ); - return sqlite4KVCursorKey(pCur->pKVCur, &p->aKey, &p->nKey); -} - -/* -** Decode a blob from a key. The blob-key is in a[0] through a[n-1]. -** xorMask is either 0x00 for ascending order or 0xff for descending. -** Store the blob in pOut. -*/ -static int decoderMemSetFromBlob( - const KVByteArray *a, KVSize n, /* The blob as a key */ - unsigned int xorMask, /* 0x00 (ascending) or 0xff (descending) */ - Mem *pOut /* Write the blob here */ -){ - int rc; - unsigned int m = 0; - int i, j, k; - - sqlite4VdbeMemSetStr(pOut, "", 0, 0, 0, 0); - rc = sqlite4VdbeMemGrow(pOut, n, 0); - if( rc==SQLITE4_OK ){ - i = 0; - j = 0; - k = 0; - while( i=8 ){ - pOut->z[k++] = (m>>(j-8))&0xff; - j -= 8; - } - } - if( j>0 ){ - pOut->z[k] = m<<(7-j); - } - pOut->n = k; - } - return rc; -} - -/* -** Decode a numeric key encoding. Return the number of bytes in the -** encoding on success. On an error, return 0. -*/ -int sqlite4VdbeDecodeNumericKey( - const KVByteArray *aKey, /* Input encoding */ - KVSize nKey, /* Number of bytes in aKey[] */ - sqlite4_num *pVal /* Write the result here */ -){ - unsigned int i, y; - unsigned int xorMask = 0; - short e; - sqlite4_uint64 m; - sqlite4_int64 eBig; - KVByteArray aInvertedKey[4]; - - pVal->approx = 0; - pVal->sign = 0; - if( nKey<1 ) return 0; - switch( aKey[0] ){ - case 0x06: /* NaN ascending */ - case 0xf9: /* NaN descending */ - pVal->m = 0; - pVal->e = 1000; - return 1; - - case 0x07: /* -inf ascending */ - case 0xf8: /* -inf descending */ - pVal->m = 1; - pVal->sign = 1; - pVal->e = 1000; - return 1; - - case 0x15: /* zero ascending */ - case 0xea: /* zero descending */ - pVal->m = 0; - pVal->e = 0; - return 1; - - case 0x23: /* +inf ascending */ - case 0xdc: /* +inf descending */ - pVal->m = 1; - pVal->e = 1000; - return 1; - - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - case 0x10: - case 0x11: - case 0x12: - case 0x13: /* -medium ascending */ - pVal->sign = 1; - xorMask = 0xff; - e = 0x13 - aKey[0]; - i = 1; - break; - - case 0xf6: - case 0xf5: - case 0xf4: - case 0xf3: - case 0xf2: - case 0xf1: - case 0xf0: - case 0xef: - case 0xee: - case 0xed: - case 0xec: /* -medium descending */ - pVal->sign = 1; - e = aKey[0] - 0xec; - i = 1; - break; - - case 0x17: - case 0x18: - case 0x19: - case 0x1a: - case 0x1b: - case 0x1c: - case 0x1d: - case 0x1e: - case 0x1f: - case 0x20: - case 0x21: /* +medium ascending */ - e = aKey[0] - 0x17; - i = 1; - break; - - case 0xe8: - case 0xe7: - case 0xe6: - case 0xe5: - case 0xe4: - case 0xe3: - case 0xe2: - case 0xe1: - case 0xe0: - case 0xdf: - case 0xde: /* +medium descending */ - e = 0xe8 - aKey[0]; - xorMask = 0xff; - i = 1; - break; - - case 0x14: /* -small ascending */ - case 0xe9: /* +small descending */ - i = 1 + sqlite4GetVarint64(aKey+1, 2, &eBig); - e = (short)-eBig; - xorMask = 0xff; - break; - - case 0x16: /* +small ascending */ - case 0xeb: /* -small descending */ - aInvertedKey[0] = aKey[1] ^ 0xff; - aInvertedKey[1] = aKey[2] ^ 0xff; - i = 1 + sqlite4GetVarint64(aInvertedKey, 2, &eBig); - e = (short)-eBig; - break; - - case 0x08: /* -large ascending */ - case 0xdd: /* +large descending */ - aInvertedKey[0] = aKey[1] ^ 0xff; - aInvertedKey[1] = aKey[2] ^ 0xff; - i = 1 + sqlite4GetVarint64(aInvertedKey, 2, &eBig); - e = (short)eBig; - xorMask = 0xff; - break; - - case 0x22: /* +large ascending */ - case 0xf7: /* -large descending */ - i = 1 + sqlite4GetVarint64(aKey+1, 2, &eBig); - e = (short)eBig; - break; - - default: - return 0; - } - m = 0; - do{ - y = aKey[i++] ^ xorMask; - m = m*100 + y/2; - e--; - }while( y & 1 ); - if( m==0 ) return 0; - - pVal->m = m; - pVal->e = 2*e; - return i; -} - -/* -** This is a private method for the RowDecoder object. -** -** Attempt to extract a single column value from the key of the current -** key/value pair. If beginning of the value is iOfst bytes from the beginning -** of the key. If affReal is true, then force numeric values to be floating -** point. Write the result in pOut. Or return non-zero if there is an -** error. -*/ -static int decoderFromKey( - RowDecoder *p, /* The current key/value pair */ - int affReal, /* True to coerce numbers to floating point */ - sqlite4_int64 iOfst, /* Offset of value in the key */ - Mem *pOut /* Write the results here */ -){ - int rc; - KVSize i; - KVSize n; - const KVByteArray *a; - char *z; - - if( iOfst<0 ){ - return SQLITE4_CORRUPT_BKPT; - } - rc = decoderFetchKey(p); - if( rc ) return rc; - if( iOfst>=p->nKey ){ - return SQLITE4_CORRUPT_BKPT; - } - a = p->aKey; - n = p->nKey; - switch( a[iOfst++] ){ - case 0x05: case 0xFA: /* NULL */ - case 0x06: case 0xF9: { /* NaN */ - sqlite4VdbeMemSetNull(pOut); - break; - } - - case 0x24: { /* Text (ascending index) */ - for(i=iOfst; iz; - for(i=n-1; i>=0; i--) *(z++) ^= 0xFF; - } - break; - } - - case 0x25: { /* Blob (ascending index) */ - for(i=iOfst; iz; - for(i=n-iOfst; i>0; i--) *(z++) ^= 0xFF; - } - break; - } - default: { - sqlite4_num v; - i = sqlite4VdbeDecodeNumericKey(a+iOfst-1, n-iOfst+1, &v); - if( i==0 ){ - rc = SQLITE4_CORRUPT_BKPT; - }else{ - sqlite4VdbeMemSetNum(pOut, v, affReal ? MEM_Real : MEM_Int); - rc = SQLITE4_OK; - } - break; - } - }; - return rc; -} - -/* -** Decode a single column from a key/value pair taken from the storage -** engine. The key/value pair to be decoded is the one that the VdbeCursor -** or KVCursor is currently pointing to. -** -** iVal is the column index of the value. 0 is the first column of the -** value. If N is the number of columns in the value and iVal>=N then -** the result is pDefault. Write the result into pOut. Return SQLITE4_OK -** on success or an appropriate error code on failure. -** -** The key is referenced only if the iVal-th column in the value is either -** the 22 or 23 header code which indicates that the value is stored in the -** key instead. -*/ -int sqlite4VdbeDecoderGetColumn( - RowDecoder *p, /* The decoder for the whole string */ +** Decode a single value from a data string. +*/ +int sqlite4VdbeDecodeValue( + ValueDecoder *p, /* The decoder for the whole string */ int iVal, /* Index of the value to decode. First is 0 */ Mem *pDefault, /* The default value. Often NULL */ Mem *pOut /* Write the result here */ ){ u32 size; /* Size of a field */ @@ -432,44 +77,35 @@ int cclass; /* class of content */ int n; /* Offset into the header */ int i; /* Loop counter */ int sz; /* Size of a varint */ int endHdr; /* First byte past header */ - int rc; /* Return code */ sqlite4VdbeMemSetNull(pOut); assert( iVal<=p->mxCol ); - rc = decoderFetchData(p); - if( rc ) return rc; - if( p->a==0 ) return SQLITE4_OK; n = sqlite4GetVarint64(p->a, p->n, &ofst); if( n==0 ) return SQLITE4_CORRUPT; ofst += n; endHdr = ofst; if( endHdr>p->n ) return SQLITE4_CORRUPT; for(i=0; i<=iVal && na+n, p->n-n, &type); if( sz==0 ) return SQLITE4_CORRUPT; n += sz; - if( type>=22 ){ /* STRING, BLOB, KEY, and TYPED */ - cclass = (type-22)%4; + if( type>=22 ){ + cclass = (type-22)%3; if( cclass==2 ){ - size = 0; /* KEY */ - }else{ - size = (type-22)/4; - if( cclass==3 ){ /* The TYPED header code */ - sz = sqlite4GetVarint64(p->a+n, p->n-n, &subtype); - if( sz==0 ) return SQLITE4_CORRUPT; - n += sz; - } - } - }else if( type<=2 ){ /* NULL, ZERO, and ONE */ + sz = sqlite4GetVarint64(p->a+n, p->n-n, &subtype); + if( sz==0 ) return SQLITE4_CORRUPT; + n += sz; + } + size = (type-22)/3; + }else if( type<=2 ){ size = 0; - }else if( type<=10 ){ /* INT */ + }else if( type<=10 ){ size = type - 2; }else{ - assert( type>=11 && type<=21 ); /* NUM */ size = type - 9; } if( i> 2); if( e & 0x02 ) num.e = -1 * num.e; if( e & 0x01 ) num.sign = 1; pOut->u.num = num; MemSetTypeFlag(pOut, MEM_Real); + }else if( cclass==0 ){ if( size==0 ){ sqlite4VdbeMemSetStr(pOut, "", 0, SQLITE4_UTF8, SQLITE4_TRANSIENT, 0); }else if( p->a[ofst]>0x02 ){ sqlite4VdbeMemSetStr(pOut, (char*)(p->a+ofst), size, @@ -508,17 +145,13 @@ }else{ static const u8 enc[] = {SQLITE4_UTF8,SQLITE4_UTF16LE,SQLITE4_UTF16BE }; sqlite4VdbeMemSetStr(pOut, (char*)(p->a+ofst+1), size-1, enc[p->a[ofst]], SQLITE4_TRANSIENT, 0); } - }else if( cclass==2 ){ - unsigned int k = (type - 24)/4; - return decoderFromKey(p, (k&1)!=0, k/2, pOut); }else{ sqlite4VdbeMemSetStr(pOut, (char*)(p->a+ofst), size, 0, SQLITE4_TRANSIENT, 0); - pOut->enc = ENC(p->db); } } testcase( i==iVal ); testcase( i==iVal+1 ); if( i<=iVal ){ @@ -546,13 +179,11 @@ } return n; } /* -** Encode nIn values from array aIn[] using the data encoding. If argument -** aPermute[] is NULL, then the nIn elements are elements 0, 1 ... (nIn-1) -** of the array. Otherwise, aPermute[0], aPermute[1] ... aPermute[nIn-1]. +** Encode 1 or more values using the data encoding. ** ** Assume that affinity has already been applied to all elements of the ** input array aIn[]. ** ** Space to hold the record is obtained from sqlite4DbMalloc() and should @@ -559,11 +190,10 @@ ** be freed by the caller using sqlite4DbFree() to avoid a memory leak. */ int sqlite4VdbeEncodeData( sqlite4 *db, /* The database connection */ Mem *aIn, /* Array of values to encode */ - int *aPermute, /* Permutation or NULL (see above) */ int nIn, /* Number of entries in aIn[] */ u8 **pzOut, /* The output data record */ int *pnOut /* Bytes of content in pzOut */ ){ int i, j; @@ -586,23 +216,22 @@ rc = SQLITE4_NOMEM; goto vdbeEncodeData_error; } nOut = 9; for(i=0; iflags; + int flags = aIn[i].flags; if( flags & MEM_Null ){ aOut[nOut++] = 0; }else if( flags & MEM_Int ){ i64 i1; - i1 = sqlite4_num_to_int64(pIn->u.num, 0); + i1 = sqlite4_num_to_int64(aIn[i].u.num, 0); n = significantBytes(i1); aOut[nOut++] = n+2; nPayload += n; aAux[i].n = n; }else if( flags & MEM_Real ){ - sqlite4_num *p = &pIn->u.num; + sqlite4_num *p = &aIn[i].u.num; int e; assert( p->sign==0 || p->sign==1 ); if( p->e<0 ){ e = (p->e*-4) + 2 + p->sign; }else{ @@ -612,35 +241,34 @@ n += sqlite4PutVarint64(aAux[i].z+n, p->m); aAux[i].n = n; aOut[nOut++] = n+9; nPayload += n; }else if( flags & MEM_Str ){ - n = pIn->n; - if( n && (encoding!=SQLITE4_UTF8 || pIn->z[0]<3) ) n++; + n = aIn[i].n; + if( n && (encoding!=SQLITE4_UTF8 || aIn[i].z[0]<2) ) n++; nPayload += n; - nOut += sqlite4PutVarint64(aOut+nOut, 22+4*(sqlite4_int64)n); + nOut += sqlite4PutVarint64(aOut+nOut, 22+3*(sqlite4_int64)n); }else{ - n = pIn->n; + n = aIn[i].n; assert( flags & MEM_Blob ); nPayload += n; - nOut += sqlite4PutVarint64(aOut+nOut, 23+4*(sqlite4_int64)n); + nOut += sqlite4PutVarint64(aOut+nOut, 23+3*(sqlite4_int64)n); } } nHdr = nOut - 9; n = sqlite4PutVarint64(aOut, nHdr); for(i=n, j=9; jflags; + int flags = aIn[i].flags; if( flags & MEM_Null ){ /* No content */ }else if( flags & MEM_Int ){ sqlite4_int64 v; - v = sqlite4_num_to_int64(pIn->u.num, 0); + v = sqlite4_num_to_int64(aIn[i].u.num, 0); n = aAux[i].n; aOut[nOut+(--n)] = v & 0xff; while( n ){ v >>= 8; aOut[nOut+(--n)] = v & 0xff; @@ -648,22 +276,22 @@ nOut += aAux[i].n; }else if( flags & MEM_Real ){ memcpy(aOut+nOut, aAux[i].z, aAux[i].n); nOut += aAux[i].n; }else if( flags & MEM_Str ){ - n = pIn->n; + n = aIn[i].n; if( n ){ if( encoding==SQLITE4_UTF16LE ) aOut[nOut++] = 1; else if( encoding==SQLITE4_UTF16BE ) aOut[nOut++] = 2; - else if( pIn->z[0]<3 ) aOut[nOut++] = 0; - memcpy(aOut+nOut, pIn->z, n); + else if( aIn[i].z[0]<2 ) aOut[nOut++] = 0; + memcpy(aOut+nOut, aIn[i].z, n); nOut += n; } }else{ assert( flags & MEM_Blob ); - memcpy(aOut+nOut, pIn->z, pIn->n); - nOut += pIn->n; + memcpy(aOut+nOut, aIn[i].z, aIn[i].n); + nOut += aIn[i].n; } } *pzOut = aOut; *pnOut = nOut; @@ -725,15 +353,13 @@ /* ** Write value num into buffer p using the key encoding. */ static void encodeNumericKey(KeyEncoder *p, sqlite4_num num){ if( num.m==0 ){ - if( sqlite4_num_isnan(num) ){ - p->aOut[p->nOut++] = 0x06; /* NaN */ - }else{ - p->aOut[p->nOut++] = 0x15; /* Numeric zero */ - } + p->aOut[p->nOut++] = 0x15; /* Numeric zero */ + }else if( sqlite4_num_isnan(num) ){ + p->aOut[p->nOut++] = 0x06; /* NaN */ }else if( sqlite4_num_isinf(num) ){ p->aOut[p->nOut++] = num.sign ? 0x07 : 0x23; /* Neg and Pos infinity */ }else{ int e; u64 m; @@ -760,11 +386,11 @@ aDigit[iDigit++] = (m % 100); m = m / 100; } e = (iDigit + (e/2)); - if( e>=11 ){ /* Large value */ + if( e>11 ){ /* Large value */ if( num.sign==0 ){ p->aOut[p->nOut++] = 0x22; putVarint64(p, e, 0); }else{ p->aOut[p->nOut++] = 0x08; @@ -849,15 +475,12 @@ if( enlargeEncoderAllocation(p, pMem->n*4 + 2) ) return SQLITE4_NOMEM; p->aOut[p->nOut++] = 0x24; /* Text */ if( pColl==0 || pColl->xMkKey==0 ){ const char *z = (const char *)sqlite4ValueText(pMem, SQLITE4_UTF8); if( z ){ - const char *zCsr = z; - const char *zEnd = &z[pMem->n]; - while( *zCsr && zCsraOut+p->nOut, z, (zCsr-z)); - p->nOut += (zCsr-z); + memcpy(p->aOut+p->nOut, z, pMem->n); + p->nOut += pMem->n; } }else{ int rc; /* xMkKey() return code */ int nReq; /* Space required by xMkKey() */ int nSpc; /* Space available */ @@ -893,11 +516,11 @@ a = (u8*)pMem->z; s = 1; t = 0; if( enlargeEncoderAllocation(p, (n*8+6)/7 + 2) ) return SQLITE4_NOMEM; p->aOut[p->nOut++] = 0x25; /* Blob */ - for(i=0; iaOut[p->nOut++] = 0x80 | t | (x>>s); if( s<7 ){ t = x<<(7-s); s++; @@ -1051,5 +674,54 @@ *paOut = x.aOut; *pnOut = x.nOut; } return rc; } + +/* +** Decode an integer key encoding. Return the number of bytes in the +** encoding on success. On an error, return 0. +*/ +int sqlite4VdbeDecodeIntKey( + const KVByteArray *aKey, /* Input encoding */ + KVSize nKey, /* Number of bytes in aKey[] */ + sqlite4_int64 *pVal /* Write the result here */ +){ + int isNeg; + int e, x; + int i; + sqlite4_int64 m; + KVByteArray aBuf[12]; + + if( nKey<2 ) return 0; + if( nKey>sizeof(aBuf) ) nKey = sizeof(aBuf); + x = aKey[0]; + if( x>=0x09 && x<=0x13 ){ + isNeg = 1; + memcpy(aBuf, aKey, nKey); + aKey = aBuf; + for(i=1; i=0x17 && x<=0x21 ){ + isNeg = 0; + e = x-0x17; + }else if( x==0x15 ){ + *pVal = 0; + return 1; + }else{ + return 0; + } + m = 0; + i = 1; + do{ + m = m*100 + aKey[i]/2; + e--; + }while( aKey[i++] & 1 ); + while( (e--)>0 ){ m = m*100; } + + if( isNeg ){ + *pVal = -m; + }else{ + *pVal = m; + } + return m==0 ? 0 : i; +} Index: src/vdbecursor.c ================================================================== --- src/vdbecursor.c +++ src/vdbecursor.c @@ -1,7 +1,7 @@ /* -** 2012-02-16 +** 2012 February 16 ** ** 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. @@ -31,40 +31,28 @@ ** Return SQLITE4_OK on success. Return SQLITE4_NOTFOUND if the table is empty. * Other error codes are also possible for various kinds of errors. */ int sqlite4VdbeSeekEnd(VdbeCursor *pC, int iEnd){ KVCursor *pCur = pC->pKVCur; - int rc; + const KVByteArray *aKey; + KVSize nKey; KVSize nProbe; + int rc; KVByteArray aProbe[16]; assert( iEnd==(+1) || iEnd==(-1) || iEnd==(-2) ); - if( pC->iRoot==KVSTORE_ROOT ){ - if( iEnd>0 ){ - rc = sqlite4KVCursorSeek(pCur, (const KVByteArray *)"\00", 1, iEnd); - }else{ - nProbe = sqlite4PutVarint64(aProbe, LARGEST_INT64); - rc = sqlite4KVCursorSeek(pCur, aProbe, nProbe, iEnd); - } - if( rc==SQLITE4_INEXACT ) rc = SQLITE4_OK; - }else{ - const KVByteArray *aKey; - KVSize nKey; - - nProbe = sqlite4PutVarint64(aProbe, pC->iRoot); - aProbe[nProbe] = 0xFF; - - rc = sqlite4KVCursorSeek(pCur, aProbe, nProbe+(iEnd<0), iEnd); - if( rc==SQLITE4_OK ){ - rc = SQLITE4_CORRUPT_BKPT; - }else if( rc==SQLITE4_INEXACT ){ - rc = sqlite4KVCursorKey(pCur, &aKey, &nKey); - if( rc==SQLITE4_OK && (nKeyrowChnged = 1; + nProbe = sqlite4PutVarint64(aProbe, pC->iRoot); + aProbe[nProbe] = 0xFF; + + rc = sqlite4KVCursorSeek(pCur, aProbe, nProbe+(iEnd<0), iEnd); + if( rc==SQLITE4_OK ){ + rc = SQLITE4_CORRUPT_BKPT; + }else if( rc==SQLITE4_INEXACT ){ + rc = sqlite4KVCursorKey(pCur, &aKey, &nKey); + if( rc==SQLITE4_OK && (nKeyiRoot!=KVSTORE_ROOT ){ + if( rc==SQLITE4_OK ){ rc = sqlite4KVCursorKey(pCur, &aKey, &nKey); if( rc==SQLITE4_OK ){ iTabno = 0; sqlite4GetVarint64(aKey, nKey, &iTabno); if( iTabno!=pC->iRoot ) rc = SQLITE4_NOTFOUND; } } - pC->rowChnged = 1; return rc; } /* ** Move a VDBE cursor to the previous element in its table. @@ -102,72 +89,15 @@ KVSize nKey; int rc; sqlite4_uint64 iTabno; rc = sqlite4KVCursorPrev(pCur); - if( rc==SQLITE4_OK && pC->iRoot!=KVSTORE_ROOT ){ + if( rc==SQLITE4_OK ){ rc = sqlite4KVCursorKey(pCur, &aKey, &nKey); if( rc==SQLITE4_OK ){ iTabno = 0; sqlite4GetVarint64(aKey, nKey, &iTabno); if( iTabno!=pC->iRoot ) rc = SQLITE4_NOTFOUND; } } - pC->rowChnged = 1; - return rc; -} - - -/* -** Close a VDBE cursor and release all the resources that cursor -** happens to hold. -*/ -void sqlite4VdbeFreeCursor(VdbeCursor *pCx){ - if( pCx==0 ){ - return; - } - sqlite4Fts5Close(pCx->pFts); - if( pCx->pKVCur ){ - sqlite4KVCursorClose(pCx->pKVCur); - } - if( pCx->pTmpKV ){ - sqlite4KVStoreClose(pCx->pTmpKV); - } - if( pCx->pDecoder ){ - sqlite4VdbeDecoderDestroy(pCx->pDecoder); - pCx->pDecoder = 0; - } - sqlite4_buffer_clear(&pCx->sSeekKey); -#ifndef SQLITE4_OMIT_VIRTUALTABLE - if( pCx->pVtabCursor ){ - sqlite4_vtab_cursor *pVtabCursor = pCx->pVtabCursor; - const sqlite4_module *pModule = pCx->pModule; - p->inVtabMethod = 1; - pModule->xClose(pVtabCursor); - p->inVtabMethod = 0; - } -#endif -} - - -/* -** Cursor pPk is open on a primary key index. If there is currently a -** deferred seek pending on the cursor, do the actual seek now. -** -** If the operation is a success, SQLITE4_OK is returned. Or, if the -** required entry is not found in the PK index, SQLITE4_CORRUPT. Or if -** some other error occurs, an error code is returned. -*/ -int sqlite4VdbeCursorMoveto(VdbeCursor *pPk){ - int rc = SQLITE4_OK; /* Return code */ - if( pPk->sSeekKey.n!=0 ){ - assert( pPk->pKeyInfo->nPK==0 ); - rc = sqlite4KVCursorSeek(pPk->pKVCur, pPk->sSeekKey.p, pPk->sSeekKey.n, 0); - if( rc==SQLITE4_NOTFOUND ){ - rc = SQLITE4_CORRUPT_BKPT; - } - pPk->nullRow = 0; - pPk->sSeekKey.n = 0; - pPk->rowChnged = 1; - } return rc; } Index: src/vdbemem.c ================================================================== --- src/vdbemem.c +++ src/vdbemem.c @@ -333,17 +333,11 @@ assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) ); assert( (pMem->flags & MEM_RowSet)==0 ); assert( EIGHT_BYTE_ALIGNMENT(pMem) ); if( (pMem->flags & MEM_Int)==0 ){ - if( pMem->flags & (MEM_Real|MEM_Null) ){ - pMem->u.num = sqlite4_num_from_int64(sqlite4VdbeIntValue(pMem)); - }else{ - unsigned int flags = pMem->enc | - SQLITE4_INTEGER_ONLY|SQLITE4_PREFIX_ONLY|SQLITE4_IGNORE_WHITESPACE; - pMem->u.num = sqlite4_num_from_text(pMem->z, pMem->n, flags, 0); - } + pMem->u.num = sqlite4_num_from_int64(sqlite4VdbeIntValue(pMem)); MemSetTypeFlag(pMem, MEM_Int); } return SQLITE4_OK; } @@ -360,12 +354,11 @@ int bReal = 0; int flags = (pMem->enc | SQLITE4_PREFIX_ONLY | SQLITE4_IGNORE_WHITESPACE); assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) ); - pMem->u.num = sqlite4_num_from_text(pMem->z, pMem->n, flags, 0); - sqlite4_num_to_int64(pMem->u.num, &bReal); + pMem->u.num = sqlite4_num_from_text(pMem->z, pMem->n, flags, &bReal); MemSetTypeFlag(pMem, (bReal ? MEM_Real : MEM_Int)); } assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 ); pMem->flags &= ~(MEM_Str|MEM_Blob); return SQLITE4_OK; Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -18,197 +18,31 @@ */ #include "sqliteInt.h" /* For VdbeCodecEncodeKey() - revisit this */ #include "vdbeInt.h" + /* ** Trace output macros */ #if defined(SQLITE4_TEST) || defined(SQLITE4_DEBUG) -/***/ int sqlite4WhereTrace = 0; +int sqlite4WhereTrace = 0; #endif -#if defined(SQLITE4_DEBUG) \ - && (defined(SQLITE4_TEST) || defined(SQLITE4_ENABLE_WHERETRACE)) -# define WHERETRACE(K,X) if(sqlite4WhereTrace&(K)) sqlite4DebugPrintf X -# define WHERETRACE_ENABLED 1 +#if defined(SQLITE4_TEST) && defined(SQLITE4_DEBUG) +# define WHERETRACE(X) if(sqlite4WhereTrace) sqlite4DebugPrintf X #else -# define WHERETRACE(K,X) +# define WHERETRACE(X) #endif /* Forward reference */ typedef struct WhereClause WhereClause; typedef struct WhereMaskSet WhereMaskSet; typedef struct WhereOrInfo WhereOrInfo; typedef struct WhereAndInfo WhereAndInfo; -typedef struct WhereLevel WhereLevel; -typedef struct WhereLoop WhereLoop; -typedef struct WherePath WherePath; -typedef struct WhereTerm WhereTerm; -typedef struct WhereLoopBuilder WhereLoopBuilder; -typedef struct WhereScan WhereScan; -typedef struct WhereOrCost WhereOrCost; -typedef struct WhereOrSet WhereOrSet; - -/* -** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The -** maximum cost for ordinary tables is 64*(2**63) which becomes 6900. -** (Virtual tables can return a larger cost, but let's assume they do not.) -** So all costs can be stored in a 16-bit unsigned integer without risk -** of overflow. -** -** Costs are estimates, so don't go to the computational trouble to compute -** 10*log2(X) exactly. Instead, a close estimate is used. Any value of -** X<=1 is stored as 0. X=2 is 10. X=3 is 16. X=1000 is 99. etc. -** -** The tool/wherecosttest.c source file implements a command-line program -** that will convert between WhereCost to integers and do addition and -** multiplication on WhereCost values. That command-line program is a -** useful utility to have around when working with this module. -*/ -typedef unsigned short int WhereCost; - -/* -** This object contains information needed to implement a single nested -** loop in WHERE clause. -** -** Contrast this object with WhereLoop. This object describes the -** implementation of the loop. WhereLoop describes the algorithm. -** This object contains a pointer to the WhereLoop algorithm as one of -** its elements. -** -** The WhereInfo object contains a single instance of this object for -** each term in the FROM clause (which is to say, for each of the -** nested loops as implemented). The order of WhereLevel objects determines -** the loop nested order, with WhereInfo.a[0] being the outer loop and -** WhereInfo.a[WhereInfo.nLevel-1] being the inner loop. -*/ -struct WhereLevel { - int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */ - int iTabCur; /* The VDBE cursor used to access the table */ - int iIdxCur; /* The VDBE cursor used to access pIdx */ - int addrBrk; /* Jump here to break out of the loop */ - int addrNxt; /* Jump here to start the next IN combination */ - int addrCont; /* Jump here to continue with the next loop cycle */ - int addrFirst; /* First instruction of interior of the loop */ - u8 iFrom; /* Which entry in the FROM clause */ - u8 op, p5; /* Opcode and P5 of the opcode that ends the loop */ - int p1, p2; /* Operands of the opcode used to ends the loop */ - union { /* Information that depends on pWLoop->wsFlags */ - struct { - int nIn; /* Number of entries in aInLoop[] */ - struct InLoop { - int iCur; /* The VDBE cursor used by this IN operator */ - int addrInTop; /* Top of the IN loop */ - u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */ - } *aInLoop; /* Information about each nested IN operator */ - } in; /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */ - Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */ - } u; - struct WhereLoop *pWLoop; /* The selected WhereLoop object */ -}; - -/* -** Each instance of this object represents an algorithm for evaluating one -** term of a join. Every term of the FROM clause will have at least -** one corresponding WhereLoop object (unless INDEXED BY constraints -** prevent a query solution - which is an error) and many terms of the -** FROM clause will have multiple WhereLoop objects, each describing a -** potential way of implementing that FROM-clause term, together with -** dependencies and cost estimates for using the chosen algorithm. -** -** Query planning consists of building up a collection of these WhereLoop -** objects, then computing a particular sequence of WhereLoop objects, with -** one WhereLoop object per FROM clause term, that satisfy all dependencies -** and that minimize the overall cost. -*/ -struct WhereLoop { - Bitmask prereq; /* Bitmask of other loops that must run first */ - Bitmask maskSelf; /* Bitmask identifying table iTab */ -#ifdef SQLITE4_DEBUG - char cId; /* Symbolic ID of this loop for debugging use */ -#endif - u8 iTab; /* Position in FROM clause of table for this loop */ - u8 iSortIdx; /* Sorting index number. 0==None */ - WhereCost rSetup; /* One-time setup cost (ex: create transient index) */ - WhereCost rRun; /* Cost of running each loop */ - WhereCost nOut; /* Estimated number of output rows */ - union { - struct { /* Information for internal btree tables */ - int nEq; /* Number of equality constraints */ - Index *pIndex; /* Index used, or NULL */ - } btree; - struct { /* Information for virtual tables */ - int idxNum; /* Index number */ - u8 needFree; /* True if sqlite4_free(idxStr) is needed */ - u8 isOrdered; /* True if satisfies ORDER BY */ - u16 omitMask; /* Terms that may be omitted */ - char *idxStr; /* Index identifier string */ - } vtab; - } u; - u32 wsFlags; /* WHERE_* flags describing the plan */ - u16 nLTerm; /* Number of entries in aLTerm[] */ - /**** whereLoopXfer() copies fields above ***********************/ -# define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot) - u16 nLSlot; /* Number of slots allocated for aLTerm[] */ - WhereTerm **aLTerm; /* WhereTerms used */ - WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */ - WhereTerm *aLTermSpace[4]; /* Initial aLTerm[] space */ -}; - -/* This object holds the prerequisites and the cost of running a -** subquery on one operand of an OR operator in the WHERE clause. -** See WhereOrSet for additional information -*/ -struct WhereOrCost { - Bitmask prereq; /* Prerequisites */ - WhereCost rRun; /* Cost of running this subquery */ - WhereCost nOut; /* Number of outputs for this subquery */ -}; - -/* The WhereOrSet object holds a set of possible WhereOrCosts that -** correspond to the subquery(s) of OR-clause processing. At most -** favorable N_OR_COST elements are retained. -*/ -#define N_OR_COST 3 -struct WhereOrSet { - u16 n; /* Number of valid a[] entries */ - WhereOrCost a[N_OR_COST]; /* Set of best costs */ -}; - - -/* Forward declaration of methods */ -static int whereLoopResize(sqlite4*, WhereLoop*, int); - -/* -** Each instance of this object holds a sequence of WhereLoop objects -** that implement some or all of a query plan. -** -** Think of each WhereLoop object as a node in a graph with arcs -** showing dependences and costs for travelling between nodes. (That is -** not a completely accurate description because WhereLoop costs are a -** vector, not a scalar, and because dependences are many-to-one, not -** one-to-one as are graph nodes. But it is a useful visualization aid.) -** Then a WherePath object is a path through the graph that visits some -** or all of the WhereLoop objects once. -** -** The "solver" works by creating the N best WherePath objects of length -** 1. Then using those as a basis to compute the N best WherePath objects -** of length 2. And so forth until the length of WherePaths equals the -** number of nodes in the FROM clause. The best (lowest cost) WherePath -** at the end is the choosen query plan. -*/ -struct WherePath { - Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */ - Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */ - WhereCost nRow; /* Estimated number of rows generated by this path */ - WhereCost rCost; /* Total cost of this path */ - u8 isOrdered; /* True if this path satisfies ORDER BY */ - u8 isOrderedValid; /* True if the isOrdered field is valid */ - WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */ -}; +typedef struct WhereCost WhereCost; /* ** The query generator uses an array of instances of this structure to ** help it analyze the subexpressions of the WHERE clause. Each WHERE ** clause subexpression is separated from the others by AND operators, @@ -257,18 +91,19 @@ ** ** The number of terms in a join is limited by the number of bits ** in prereqRight and prereqAll. The default is 64 bits, hence SQLite ** is only able to process joins with 64 or fewer tables. */ +typedef struct WhereTerm WhereTerm; struct WhereTerm { Expr *pExpr; /* Pointer to the subexpression that is this term */ int iParent; /* Disable pWC->a[iParent] when this term disabled */ int leftCursor; /* Cursor number of X in "X " */ union { int leftColumn; /* Column number of X in "X " */ - WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */ - WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */ + WhereOrInfo *pOrInfo; /* Extra information if eOperator==WO_OR */ + WhereAndInfo *pAndInfo; /* Extra information if eOperator==WO_AND */ } u; u16 eOperator; /* A WO_xx value describing */ u8 wtFlags; /* TERM_xxx bit flags. See below */ u8 nChild; /* Number of children that must disable us */ WhereClause *pWC; /* The clause this term is part of */ @@ -290,26 +125,10 @@ # define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */ #else # define TERM_VNULL 0x00 /* Disabled if not using stat3 */ #endif -/* -** An instance of the WhereScan object is used as an iterator for locating -** terms in the WHERE clause that are useful to the query planner. -*/ -struct WhereScan { - WhereClause *pOrigWC; /* Original, innermost WhereClause */ - WhereClause *pWC; /* WhereClause currently being scanned */ - char *zCollName; /* Required collating sequence, if not NULL */ - char idxaff; /* Must match this affinity, if zCollName!=NULL */ - unsigned char nEquiv; /* Number of entries in aEquiv[] */ - unsigned char iEquiv; /* Next unused slot in aEquiv[] */ - u32 opMask; /* Acceptable operators */ - int k; /* Resume scanning at this->pWC->a[this->k] */ - int aEquiv[22]; /* Cursor,Column pairs for equivalence classes */ -}; - /* ** An instance of the following structure holds all information about a ** WHERE clause. Mostly this is a container for one or more WhereTerms. ** ** Explanation of pOuter: For a WHERE clause of the form @@ -319,13 +138,16 @@ ** There are separate WhereClause objects for the whole clause and for ** the subclauses "(b AND c)" and "(d AND e)". The pOuter field of the ** subclauses points to the WhereClause object for the whole clause. */ struct WhereClause { - WhereInfo *pWInfo; /* WHERE clause processing context */ + Parse *pParse; /* The parser context */ + WhereMaskSet *pMaskSet; /* Mapping of table cursor numbers to bitmasks */ + Bitmask vmask; /* Bitmask identifying virtual table cursors */ WhereClause *pOuter; /* Outer conjunction */ u8 op; /* Split operator. TK_AND or TK_OR */ + u16 wctrlFlags; /* Might include WHERE_AND_ONLY */ int nTerm; /* Number of terms */ int nSlot; /* Number of entries in a[] */ WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */ #if defined(SQLITE4_SMALL_STACK) WhereTerm aStatic[1]; /* Initial static space for a[] */ @@ -354,11 +176,11 @@ /* ** An instance of the following structure keeps track of a mapping ** between VDBE cursor numbers and bits of the bitmasks in WhereTerm. ** ** The VDBE cursor numbers are small integers contained in -** SrcListItem.iCursor and Expr.iTable fields. For any given WHERE +** SrcList_item.iCursor and Expr.iTable fields. For any given WHERE ** clause, the cursor numbers might not begin with 0 and they might ** contain gaps in the numbering sequence. But we want to make maximum ** use of the bits in our bitmasks. This structure provides a mapping ** from the sparse cursor numbers into consecutive integers beginning ** with 0. @@ -381,59 +203,23 @@ int n; /* Number of assigned cursor values */ int ix[BMS]; /* Cursor assigned to each bit */ }; /* -** This object is a convenience wrapper holding all information needed -** to construct WhereLoop objects for a particular query. -*/ -struct WhereLoopBuilder { - WhereInfo *pWInfo; /* Information about this WHERE */ - WhereClause *pWC; /* WHERE clause terms */ - ExprList *pOrderBy; /* ORDER BY clause */ - WhereLoop *pNew; /* Template WhereLoop */ - WhereOrSet *pOrSet; /* Record best loops here, if not NULL */ -}; - -/* -** The WHERE clause processing routine has two halves. The -** first part does the start of the WHERE loop and the second -** half does the tail of the WHERE loop. An instance of -** this structure is returned by the first half and passed -** into the second half to give some continuity. -** -** An instance of this object holds the complete state of the query -** planner. -*/ -struct WhereInfo { - Parse *pParse; /* Parsing and code generating context */ - SrcList *pTabList; /* List of tables in the join */ - ExprList *pOrderBy; /* The ORDER BY clause or NULL */ - ExprList *pResultSet; /* Result set. DISTINCT operates on these */ - WhereLoop *pLoops; /* List of all WhereLoop objects */ - Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ - WhereCost nRowOut; /* Estimated number of output rows */ - u16 wctrlFlags; /* Flags originally passed to sqlite4WhereBegin() */ - u8 bOBSat; /* ORDER BY satisfied by indices */ - u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */ - u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ - u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */ - u8 nLevel; /* Number of nested loop */ - int iTop; /* The very beginning of the WHERE loop */ - int iContinue; /* Jump here to continue with next record */ - int iBreak; /* Jump here to break out of the loop */ - int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ - WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ - WhereClause sWC; /* Decomposition of the WHERE clause */ - WhereLevel a[1]; /* Information about each nest loop in WHERE */ -}; - -/* -** Bitmasks for the operators on WhereTerm objects. These are all -** operators that are of interest to the query planner. An -** OR-ed combination of these values can be used when searching for -** particular WhereTerms within a WhereClause. +** A WhereCost object records a lookup strategy and the estimated +** cost of pursuing that strategy. +*/ +struct WhereCost { + WherePlan plan; /* The lookup strategy */ + double rCost; /* Overall cost of pursuing this search strategy */ + Bitmask used; /* Bitmask of cursors used by this plan */ +}; + +/* +** Bitmasks for the operators that indices are able to exploit. An +** OR-ed combination of these values can be used when searching for +** terms in the where clause. */ #define WO_IN 0x001 #define WO_EQ 0x002 #define WO_LT (WO_EQ<<(TK_LT-TK_EQ)) #define WO_LE (WO_EQ<<(TK_LE-TK_EQ)) @@ -441,161 +227,64 @@ #define WO_GE (WO_EQ<<(TK_GE-TK_EQ)) #define WO_MATCH 0x040 #define WO_ISNULL 0x080 #define WO_OR 0x100 /* Two or more OR-connected terms */ #define WO_AND 0x200 /* Two or more AND-connected terms */ -#define WO_EQUIV 0x400 /* Of the form A==B, both columns */ #define WO_NOOP 0x800 /* This term does not restrict search space */ #define WO_ALL 0xfff /* Mask of all possible WO_* values */ #define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */ /* -** These are definitions of bits in the WhereLoop.wsFlags field. -** The particular combination of bits in each WhereLoop help to -** determine the algorithm that WhereLoop represents. -*/ -#define WHERE_COLUMN_EQ 0x00000001 /* x=EXPR */ -#define WHERE_COLUMN_RANGE 0x00000002 /* xEXPR */ -#define WHERE_COLUMN_IN 0x00000004 /* x IN (...) */ -#define WHERE_COLUMN_NULL 0x00000008 /* x IS NULL */ -#define WHERE_CONSTRAINT 0x0000000f /* Any of the WHERE_COLUMN_xxx values */ -#define WHERE_TOP_LIMIT 0x00000010 /* xEXPR or x>=EXPR constraint */ -#define WHERE_BOTH_LIMIT 0x00000030 /* Both x>EXPR and x=5 ) n -= 2; - else if( n>=1 ) n -= 1; - if( x>=3 ) return (n+8)<<(x-3); - return (n+8)>>(3-x); -} - -/* -** Return the estimated number of output rows from a WHERE clause -*/ -u64 sqlite4WhereOutputRowCount(WhereInfo *pWInfo){ - return whereCostToInt(pWInfo->nRowOut); -} - -/* -** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this -** WHERE clause returns outputs for DISTINCT processing. -*/ -int sqlite4WhereIsDistinct(WhereInfo *pWInfo){ - return pWInfo->eDistinct; -} - -/* -** Return TRUE if the WHERE clause returns rows in ORDER BY order. -** Return FALSE if the output needs to be sorted. -*/ -int sqlite4WhereIsOrdered(WhereInfo *pWInfo){ - return pWInfo->bOBSat!=0; -} - -/* -** Return the VDBE address or label to jump to in order to continue -** immediately with the next row of a WHERE clause. -*/ -int sqlite4WhereContinueLabel(WhereInfo *pWInfo){ - return pWInfo->iContinue; -} - -/* -** Return the VDBE address or label to jump to in order to break -** out of a WHERE loop. -*/ -int sqlite4WhereBreakLabel(WhereInfo *pWInfo){ - return pWInfo->iBreak; -} - -/* -** Return TRUE if an UPDATE or DELETE statement can operate directly on -** the rowids returned by a WHERE clause. Return FALSE if doing an -** UPDATE or DELETE might change subsequent WHERE clause results. -*/ -int sqlite4WhereOkOnePass(WhereInfo *pWInfo){ - return pWInfo->okOnePass; -} - -/* -** Move the content of pSrc into pDest -*/ -static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){ - pDest->n = pSrc->n; - memcpy(pDest->a, pSrc->a, pDest->n*sizeof(pDest->a[0])); -} - -/* -** Try to insert a new prerequisite/cost entry into the WhereOrSet pSet. -** -** The new entry might overwrite an existing entry, or it might be -** appended, or it might be discarded. Do whatever is the right thing -** so that pSet keeps the N_OR_COST best entries seen so far. -*/ -static int whereOrInsert( - WhereOrSet *pSet, /* The WhereOrSet to be updated */ - Bitmask prereq, /* Prerequisites of the new entry */ - WhereCost rRun, /* Run-cost of the new entry */ - WhereCost nOut /* Number of outputs for the new entry */ -){ - u16 i; - WhereOrCost *p; - for(i=pSet->n, p=pSet->a; i>0; i--, p++){ - if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){ - goto whereOrInsert_done; - } - if( p->rRun<=rRun && (p->prereq & prereq)==p->prereq ){ - return 0; - } - } - if( pSet->na[pSet->n++]; - p->nOut = nOut; - }else{ - p = pSet->a; - for(i=1; in; i++){ - if( p->rRun>pSet->a[i].rRun ) p = pSet->a + i; - } - if( p->rRun<=rRun ) return 0; - } -whereOrInsert_done: - p->prereq = prereq; - p->rRun = rRun; - if( p->nOut>nOut ) p->nOut = nOut; - return 1; -} +** Value for wsFlags returned by bestIndex() and stored in +** WhereLevel.wsFlags. These flags determine which search +** strategies are appropriate. +** +** The least significant 12 bits is reserved as a mask for WO_ values above. +** The WhereLevel.wsFlags field is usually set to WO_IN|WO_EQ|WO_ISNULL. +** But if the table is the right table of a left join, WhereLevel.wsFlags +** is set to WO_IN|WO_EQ. The WhereLevel.wsFlags field can then be used as +** the "op" parameter to findTerm when we are resolving equality constraints. +** ISNULL constraints will then not be used on the right table of a left +** join. Tickets #2177 and #2189. +*/ +#define WHERE_COLUMN_EQ 0x00010000 /* x=EXPR or x IN (...) or x IS NULL */ +#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 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 xpWInfo = pWInfo; + pWC->pParse = pParse; + pWC->pMaskSet = pMaskSet; pWC->pOuter = 0; pWC->nTerm = 0; pWC->nSlot = ArraySize(pWC->aStatic); pWC->a = pWC->aStatic; + pWC->vmask = 0; + pWC->wctrlFlags = wctrlFlags; } /* Forward reference */ static void whereClauseClear(WhereClause*); @@ -620,11 +309,11 @@ ** itself is not freed. This routine is the inverse of whereClauseInit(). */ static void whereClauseClear(WhereClause *pWC){ int i; WhereTerm *a; - sqlite4 *db = pWC->pWInfo->pParse->db; + sqlite4 *db = pWC->pParse->db; for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){ if( a->wtFlags & TERM_DYNAMIC ){ sqlite4ExprDelete(db, a->pExpr); } if( a->wtFlags & TERM_ORINFO ){ @@ -635,36 +324,10 @@ } if( pWC->a!=pWC->aStatic ){ sqlite4DbFree(db, pWC->a); } } - - -/* -** Skip over any TK_COLLATE and/or TK_AS operators at the root of -** an expression. -** -** NOTE: This function was added when the NGQP was imported from SQLite3. -** At present it is not actually possible for Expr.op to be set to -** TK_COLLATE. But will be if the way Expr objects represent collation -** sequences is changed to match SQLite3. -*/ -static Expr *sqlite4ExprSkipCollate(Expr *pExpr){ - assert( pExpr==0 || pExpr->op!=TK_COLLATE ); - - while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){ - pExpr = pExpr->pLeft; - } - return pExpr; -} - -/* -** A bit in a Bitmask -*/ -#define MASKBIT(n) (((Bitmask)1)<<(n)) - - /* ** Add a single new WhereTerm entry to the WhereClause object pWC. ** The new WhereTerm object is constructed from Expr p and with wtFlags. ** The index in pWC->a[] of the new WhereTerm is returned on success. @@ -687,11 +350,11 @@ WhereTerm *pTerm; int idx; testcase( wtFlags & TERM_VIRTUAL ); /* EV: R-00211-15100 */ if( pWC->nTerm>=pWC->nSlot ){ WhereTerm *pOld = pWC->a; - sqlite4 *db = pWC->pWInfo->pParse->db; + sqlite4 *db = pWC->pParse->db; pWC->a = sqlite4DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); if( pWC->a==0 ){ if( wtFlags & TERM_DYNAMIC ){ sqlite4ExprDelete(db, p); } @@ -703,11 +366,11 @@ sqlite4DbFree(db, pOld); } pWC->nSlot = sqlite4DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); } pTerm = &pWC->a[idx = pWC->nTerm++]; - pTerm->pExpr = sqlite4ExprSkipCollate(p); + pTerm->pExpr = p; pTerm->wtFlags = wtFlags; pTerm->pWC = pWC; pTerm->iParent = -1; return idx; } @@ -727,12 +390,12 @@ ** ** In the previous sentence and in the diagram, "slot[]" refers to ** the WhereClause.a[] array. The slot[] array grows as needed to contain ** all terms of the WHERE clause. */ -static void whereSplit(WhereClause *pWC, Expr *pExpr, u8 op){ - pWC->op = op; +static void whereSplit(WhereClause *pWC, Expr *pExpr, int op){ + pWC->op = (u8)op; if( pExpr==0 ) return; if( pExpr->op!=op ){ whereClauseInsert(pWC, pExpr, 0); }else{ whereSplit(pWC, pExpr->pLeft, op); @@ -739,13 +402,13 @@ whereSplit(pWC, pExpr->pRight, op); } } /* -** Initialize a WhereMaskSet object +** Initialize an expression mask set (a WhereMaskSet object) */ -#define initMaskSet(P) (P)->n=0 +#define initMaskSet(P) memset(P, 0, sizeof(*P)) /* ** Return the bitmask for the given cursor number. Return 0 if ** iCursor is not in the set. */ @@ -752,11 +415,11 @@ static Bitmask getMask(WhereMaskSet *pMaskSet, int iCursor){ int i; assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 ); for(i=0; in; i++){ if( pMaskSet->ix[i]==iCursor ){ - return MASKBIT(i); + return ((Bitmask)1)<n < ArraySize(pMaskSet->ix) ); pMaskSet->ix[pMaskSet->n++] = iCursor; } /* -** These routine walk (recursively) an expression tree and generates +** This routine walks (recursively) an expression tree and generates ** a bitmask indicating which tables are used in that expression ** tree. +** +** In order for this routine to work, the calling function must have +** previously invoked sqlite4ResolveExprNames() on the expression. See +** the header comment on that routine for additional information. +** The sqlite4ResolveExprNames() routines looks for column names and +** sets their opcodes to TK_COLUMN and their Expr.iTable fields to +** the VDBE cursor number of the table. This routine just has to +** translate the cursor numbers into bitmask values and OR all +** the bitmasks together. */ static Bitmask exprListTableUsage(WhereMaskSet*, ExprList*); static Bitmask exprSelectTableUsage(WhereMaskSet*, Select*); static Bitmask exprTableUsage(WhereMaskSet *pMaskSet, Expr *p){ Bitmask mask = 0; @@ -828,11 +500,11 @@ } /* ** Return TRUE if the given operator is one of the operators that is ** allowed for an indexable WHERE clause term. The allowed operators are -** "=", "<", ">", "<=", ">=", "IN", and "IS NULL" +** "=", "<", ">", "<=", ">=", and "IN". ** ** IMPLEMENTATION-OF: R-59926-26393 To be usable by an index a term must be ** of one of the following forms: column = expression column > expression ** column >= expression column < expression column <= expression ** expression = column expression > column expression >= column @@ -854,35 +526,27 @@ /* ** Commute a comparison operator. Expressions of the form "X op Y" ** are converted into "Y op X". ** -** If left/right precedence rules come into play when determining the -** collating sequence, then COLLATE operators are adjusted to ensure -** that the collating sequence does not change. For example: -** "Y collate NOCASE op X" becomes "X op Y" because any collation sequence on +** If a collation sequence is associated with either the left or right +** side of the comparison, it remains associated with the same side after +** the commutation. So "Y collate NOCASE op X" becomes +** "X collate NOCASE op Y". This is because any collation sequence on ** the left hand side of a comparison overrides any collation sequence ** attached to the right. For the same reason the EP_ExpCollate flag ** is not commuted. */ static void exprCommute(Parse *pParse, Expr *pExpr){ u16 expRight = (pExpr->pRight->flags & EP_ExpCollate); u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate); assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN ); - if( expRight==expLeft ){ - /* Either X and Y both have COLLATE operator or neither do */ - if( expRight ){ - /* Both X and Y have COLLATE operators. Make sure X is always - ** used by clearing the EP_ExpCollate flag from Y. */ - pExpr->pRight->flags &= ~EP_ExpCollate; - }else if( sqlite4ExprCollSeq(pParse, pExpr->pLeft)!=0 ){ - /* Neither X nor Y have COLLATE operators, but X has a non-default - ** collating sequence. So add the EP_ExpCollate marker on X to cause - ** it to be searched first. */ - pExpr->pLeft->flags |= EP_ExpCollate; - } - } + pExpr->pRight->pColl = sqlite4ExprCollSeq(pParse, pExpr->pRight); + pExpr->pLeft->pColl = sqlite4ExprCollSeq(pParse, pExpr->pLeft); + SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl); + pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft; + pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight; SWAP(Expr*,pExpr->pRight,pExpr->pLeft); if( pExpr->op>=TK_GT ){ assert( TK_LT==TK_GT+2 ); assert( TK_GE==TK_LE+2 ); assert( TK_GT>TK_EQ ); @@ -914,248 +578,82 @@ assert( op!=TK_GT || c==WO_GT ); assert( op!=TK_GE || c==WO_GE ); return c; } -/* -** Advance to the next WhereTerm that matches according to the criteria -** established when the pScan object was initialized by whereScanInit(). -** Return NULL if there are no more matching WhereTerms. -*/ -static WhereTerm *whereScanNext(WhereScan *pScan){ - int iCur; /* The cursor on the LHS of the term */ - int iColumn; /* The column on the LHS of the term. -1 for IPK */ - Expr *pX; /* An expression being tested */ - WhereClause *pWC; /* Shorthand for pScan->pWC */ - WhereTerm *pTerm; /* The term being tested */ - int k = pScan->k; /* Where to start scanning */ - - while( pScan->iEquiv<=pScan->nEquiv ){ - iCur = pScan->aEquiv[pScan->iEquiv-2]; - iColumn = pScan->aEquiv[pScan->iEquiv-1]; - while( (pWC = pScan->pWC)!=0 ){ - for(pTerm=pWC->a+k; knTerm; k++, pTerm++){ - if( pTerm->leftCursor==iCur && pTerm->u.leftColumn==iColumn ){ - if( (pTerm->eOperator & WO_EQUIV)!=0 - && pScan->nEquivaEquiv) - ){ - int j; - pX = sqlite4ExprSkipCollate(pTerm->pExpr->pRight); - assert( pX->op==TK_COLUMN ); - for(j=0; jnEquiv; j+=2){ - if( pScan->aEquiv[j]==pX->iTable - && pScan->aEquiv[j+1]==pX->iColumn ){ - break; - } - } - if( j==pScan->nEquiv ){ - pScan->aEquiv[j] = pX->iTable; - pScan->aEquiv[j+1] = pX->iColumn; - pScan->nEquiv += 2; - } - } - if( (pTerm->eOperator & pScan->opMask)!=0 ){ - /* Verify the affinity and collating sequence match */ - if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){ - CollSeq *pColl; - Parse *pParse = pWC->pWInfo->pParse; - pX = pTerm->pExpr; - if( !sqlite4IndexAffinityOk(pX, pScan->idxaff) ){ - continue; - } - assert(pX->pLeft); - pColl = sqlite4BinaryCompareCollSeq(pParse, - pX->pLeft, pX->pRight); - if( pColl==0 ) pColl = pParse->db->pDfltColl; - if( sqlite4_stricmp(pColl->zName, pScan->zCollName) ){ - continue; - } - } - if( (pTerm->eOperator & WO_EQ)!=0 - && (pX = pTerm->pExpr->pRight)->op==TK_COLUMN - && pX->iTable==pScan->aEquiv[0] - && pX->iColumn==pScan->aEquiv[1] - ){ - continue; - } - pScan->k = k+1; - return pTerm; - } - } - } - pScan->pWC = pScan->pWC->pOuter; - k = 0; - } - pScan->pWC = pScan->pOrigWC; - k = 0; - pScan->iEquiv += 2; - } - return 0; -} - -/* -** Return the table column number of the iIdxCol'th field in the index -** keys used by index pIdx, including any appended PRIMARY KEY fields. -** If there is no iIdxCol'th field in index pIdx, return -2. -** -** Example: -** -** CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b)); -** CREATE INDEX i1 ON t1(c); -** -** Index i1 in the example above consists of three fields - the indexed -** field "c" followed by the two primary key fields. The automatic PRIMARY -** KEY index consists of two fields only. -*/ -static int idxColumnNumber(Index *pIdx, Index *pPk, int iIdxCol){ - int iRet = -2; - if( iIdxColnColumn ){ - iRet = pIdx->aiColumn[iIdxCol]; - }else if( pPk && iIdxCol<(pIdx->nColumn + pPk->nColumn) ){ - iRet = pPk->aiColumn[iIdxCol - pIdx->nColumn]; - } - return iRet; -} - -/* -** Return a pointer to a buffer containing the name of the collation -** sequence used with the iIdxCol'th field in index pIdx, including any -** appended PRIMARY KEY fields. -*/ -static char *idxColumnCollation(Index *pIdx, Index *pPk, int iIdxCol){ - char *zColl; - assert( iIdxCol<(pIdx->nColumn + pPk->nColumn) ); - if( iIdxColnColumn ){ - zColl = pIdx->azColl[iIdxCol]; - }else if( pPk && iIdxCol<(pIdx->nColumn + pPk->nColumn) ){ - zColl = pPk->azColl[iIdxCol - pIdx->nColumn]; - } - return zColl; -} - -/* -** Return the sort order (SQLITE4_SO_ASC or DESC) used by the iIdxCol'th -** field in index pIdx, including any appended PRIMARY KEY fields. -*/ -static int idxColumnSortOrder(Index *pIdx, Index *pPk, int iIdxCol){ - int iRet = SQLITE4_SO_ASC; - if( iIdxColnColumn ){ - iRet = pIdx->aSortOrder[iIdxCol]; - } - return iRet; -} - -/* -** Return the total number of fields in the index pIdx, including any -** trailing primary key fields. -*/ -static int idxColumnCount(Index *pIdx, Index *pPk){ - return (pIdx->nColumn + ((pPk==0 || pIdx==pPk) ? 0 : pPk->nColumn)); -} - -/* -** Initialize a WHERE clause scanner object. Return a pointer to the -** first match. Return NULL if there are no matches. -** -** The scanner will be searching the WHERE clause pWC. It will look -** for terms of the form "X " where X is column iColumn of table -** iCur. The must be one of the operators described by opMask. -** -** If the search is for X and the WHERE clause contains terms of the -** form X=Y then this routine might also return terms of the form -** "Y ". The number of levels of transitivity is limited, -** but is enough to handle most commonly occurring SQL statements. -** -** If X is not the INTEGER PRIMARY KEY then X must be compatible with -** index pIdx. -*/ -static WhereTerm *whereScanInit( - WhereScan *pScan, /* The WhereScan object being initialized */ - WhereClause *pWC, /* The WHERE clause to be scanned */ - int iCur, /* Cursor to scan for */ - int iColumn, /* Column to scan for */ - u32 opMask, /* Operator(s) to scan for */ - Index *pIdx /* Must be compatible with this index */ -){ - int j; - - /* memset(pScan, 0, sizeof(*pScan)); */ - pScan->pOrigWC = pWC; - pScan->pWC = pWC; - if( pIdx && iColumn>=0 ){ - Index *pPk = sqlite4FindPrimaryKey(pIdx->pTable, 0); - pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; - for(j=0; idxColumnNumber(pIdx, pPk, j)!=iColumn; j++){ - if( NEVER(j>=idxColumnCount(pIdx, pPk)) ) return 0; - } - pScan->zCollName = idxColumnCollation(pIdx, pPk, j); - }else{ - pScan->idxaff = 0; - pScan->zCollName = 0; - } - pScan->opMask = opMask; - pScan->k = 0; - pScan->aEquiv[0] = iCur; - pScan->aEquiv[1] = iColumn; - pScan->nEquiv = 2; - pScan->iEquiv = 2; - return whereScanNext(pScan); -} - /* ** Search for a term in the WHERE clause that is of the form "X " ** where X is a reference to the iColumn of table iCur and is one of ** the WO_xx operator codes specified by the op parameter. ** Return a pointer to the term. Return 0 if not found. -** -** The term returned might by Y= if there is another constraint in -** the WHERE clause that specifies that X=Y. Any such constraints will be -** identified by the WO_EQUIV bit in the pTerm->eOperator field. The -** aEquiv[] array holds X and all its equivalents, with each SQL variable -** taking up two slots in aEquiv[]. The first slot is for the cursor number -** and the second is for the column number. There are 22 slots in aEquiv[] -** so that means we can look for X plus up to 10 other equivalent values. -** Hence a search for X will return if X=A1 and A1=A2 and A2=A3 -** and ... and A9=A10 and A10=. -** -** If there are multiple terms in the WHERE clause of the form "X " -** then try for the one with no dependencies on - in other words where -** is a constant expression of some kind. Only return entries of -** the form "X Y" where Y is a column in another table if no terms of -** the form "X " exist. If no terms with a constant RHS -** exist, try to return a term that does not use WO_EQUIV. */ static WhereTerm *findTerm( WhereClause *pWC, /* The WHERE clause to be searched */ int iCur, /* Cursor number of LHS */ int iColumn, /* Column number of LHS */ Bitmask notReady, /* RHS must not overlap with this mask */ u32 op, /* Mask of WO_xx values describing operator */ Index *pIdx /* Must be compatible with this index, if not NULL */ ){ - WhereTerm *pResult = 0; - WhereTerm *p; - WhereScan scan; - - p = whereScanInit(&scan, pWC, iCur, iColumn, op, pIdx); - while( p ){ - if( (p->prereqRight & notReady)==0 ){ - if( p->prereqRight==0 && (p->eOperator&WO_EQ)!=0 ){ - return p; - } - if( pResult==0 ) pResult = p; - } - p = whereScanNext(&scan); - } - return pResult; + sqlite4 *db = pWC->pParse->db; /* Database handle */ + WhereTerm *pTerm; + int k; + + assert( iCur>=0 ); + op &= WO_ALL; + for(; pWC; pWC=pWC->pOuter){ + for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){ + if( pTerm->leftCursor==iCur + && (pTerm->prereqRight & notReady)==0 + && pTerm->u.leftColumn==iColumn + && (pTerm->eOperator & op)!=0 + ){ + if( iColumn>=0 && pIdx && pTerm->eOperator!=WO_ISNULL ){ + Table *pTab = pIdx->pTable; + const char *zColl; /* Collation sequence used by index */ + CollSeq *pColl; /* Collation sequence used by expression */ + Expr *pX = pTerm->pExpr; + int j; + Parse *pParse = pWC->pParse; + + if( !sqlite4IndexAffinityOk(pX, pTab->aCol[iColumn].affinity) ){ + continue; + } + + /* Figure out the collation sequence used by expression pX. Store + ** this in pColl. Also the collation sequence used by the index. + ** Store this one in zColl. */ + assert(pX->pLeft); + pColl = sqlite4BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); + for(j=0; pIdx->aiColumn[j]!=iColumn && jnColumn; j++); + if( j>=pIdx->nColumn ){ + zColl = pTab->aCol[iColumn].zColl; + }else{ + zColl = pIdx->azColl[j]; + } + + /* If the collation sequence used by the index is not the same as + ** that used by the expression, then this term is not a match. */ + if( pColl!=sqlite4FindCollSeq(db, zColl, 0) ) continue; + } + return pTerm; + } + } + } + return 0; } /* Forward reference */ static void exprAnalyze(SrcList*, WhereClause*, int); /* ** Call exprAnalyze on all terms in a WHERE clause. +** +** Note that exprAnalyze() might add new virtual terms onto the end of +** the WHERE clause. We do not want to analyze these virtual terms, so +** start analyzing at the end and work forward so that the added virtual +** terms are never processed. */ static void exprAnalyzeAll( SrcList *pTabList, /* the FROM clause */ WhereClause *pWC /* the WHERE clause to be analyzed */ ){ @@ -1197,14 +695,11 @@ #ifdef SQLITE4_EBCDIC if( *pnoCase ) return 0; #endif pList = pExpr->x.pList; pLeft = pList->a[1].pExpr; - if( pLeft->op!=TK_COLUMN - || sqlite4ExprAffinity(pLeft)!=SQLITE4_AFF_TEXT - || IsVirtual(pLeft->pTab) - ){ + if( pLeft->op!=TK_COLUMN || sqlite4ExprAffinity(pLeft)!=SQLITE4_AFF_TEXT ){ /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must ** be the name of an indexed column with TEXT affinity. */ return 0; } assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */ @@ -1217,11 +712,11 @@ if( op==TK_VARIABLE ){ Vdbe *pReprepare = pParse->pReprepare; int iCol = pRight->iColumn; pVal = sqlite4VdbeGetValue(pReprepare, iCol, SQLITE4_AFF_NONE); if( pVal && sqlite4_value_type(pVal)==SQLITE4_TEXT ){ - z = (char *)sqlite4_value_text(pVal, 0); + z = sqlite4_value_text(pVal, 0); } sqlite4VdbeSetVarmask(pParse->pVdbe, iCol); assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER ); }else if( op==TK_STRING ){ z = pRight->u.zToken; @@ -1328,11 +823,11 @@ ** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*') ** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6) ** ** CASE 1: ** -** If all subterms are of the form T.C=expr for some single column of C and +** If all subterms are of the form T.C=expr for some single column of C ** a single table T (as shown in example B above) then create a new virtual ** term that is an equivalent IN expression. In other words, if the term ** being analyzed is: ** ** x = expr1 OR expr2 = x OR x = expr3 @@ -1383,15 +878,15 @@ static void exprAnalyzeOrTerm( SrcList *pSrc, /* the FROM clause */ WhereClause *pWC, /* the complete WHERE clause */ int idxTerm /* Index of the OR-term to be analyzed */ ){ - WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */ - Parse *pParse = pWInfo->pParse; /* Parser context */ + Parse *pParse = pWC->pParse; /* Parser context */ sqlite4 *db = pParse->db; /* Database connection */ WhereTerm *pTerm = &pWC->a[idxTerm]; /* The term to be analyzed */ Expr *pExpr = pTerm->pExpr; /* The expression of the term */ + WhereMaskSet *pMaskSet = pWC->pMaskSet; /* Table use masks */ int i; /* Loop counters */ WhereClause *pOrWc; /* Breakup of pTerm into subterms */ WhereTerm *pOrTerm; /* A Sub-term within the pOrWc */ WhereOrInfo *pOrInfo; /* Additional information associated with pTerm */ Bitmask chngToIN; /* Tables that might satisfy case 1 */ @@ -1406,24 +901,25 @@ assert( pExpr->op==TK_OR ); pTerm->u.pOrInfo = pOrInfo = sqlite4DbMallocZero(db, sizeof(*pOrInfo)); if( pOrInfo==0 ) return; pTerm->wtFlags |= TERM_ORINFO; pOrWc = &pOrInfo->wc; - whereClauseInit(pOrWc, pWInfo); + whereClauseInit(pOrWc, pWC->pParse, pMaskSet, pWC->wctrlFlags); whereSplit(pOrWc, pExpr, TK_OR); exprAnalyzeAll(pSrc, pOrWc); if( db->mallocFailed ) return; assert( pOrWc->nTerm>=2 ); /* ** Compute the set of tables that might satisfy cases 1 or 2. */ indexable = ~(Bitmask)0; - chngToIN = ~(Bitmask)0; + chngToIN = ~(pWC->vmask); for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){ if( (pOrTerm->eOperator & WO_SINGLE)==0 ){ WhereAndInfo *pAndInfo; + assert( pOrTerm->eOperator==0 ); assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 ); chngToIN = 0; pAndInfo = sqlite4DbMallocRaw(db, sizeof(*pAndInfo)); if( pAndInfo ){ WhereClause *pAndWC; @@ -1432,20 +928,20 @@ Bitmask b = 0; pOrTerm->u.pAndInfo = pAndInfo; pOrTerm->wtFlags |= TERM_ANDINFO; pOrTerm->eOperator = WO_AND; pAndWC = &pAndInfo->wc; - whereClauseInit(pAndWC, pWC->pWInfo); + whereClauseInit(pAndWC, pWC->pParse, pMaskSet, pWC->wctrlFlags); whereSplit(pAndWC, pOrTerm->pExpr, TK_AND); exprAnalyzeAll(pSrc, pAndWC); pAndWC->pOuter = pWC; testcase( db->mallocFailed ); if( !db->mallocFailed ){ for(j=0, pAndTerm=pAndWC->a; jnTerm; j++, pAndTerm++){ assert( pAndTerm->pExpr ); if( allowedOp(pAndTerm->pExpr->op) ){ - b |= getMask(&pWInfo->sMaskSet, pAndTerm->leftCursor); + b |= getMask(pMaskSet, pAndTerm->leftCursor); } } } indexable &= b; } @@ -1452,17 +948,17 @@ }else if( pOrTerm->wtFlags & TERM_COPIED ){ /* Skip this term for now. We revisit it when we process the ** corresponding TERM_VIRTUAL term */ }else{ Bitmask b; - b = getMask(&pWInfo->sMaskSet, pOrTerm->leftCursor); + b = getMask(pMaskSet, pOrTerm->leftCursor); if( pOrTerm->wtFlags & TERM_VIRTUAL ){ WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent]; - b |= getMask(&pWInfo->sMaskSet, pOther->leftCursor); + b |= getMask(pMaskSet, pOther->leftCursor); } indexable &= b; - if( (pOrTerm->eOperator & WO_EQ)==0 ){ + if( pOrTerm->eOperator!=WO_EQ ){ chngToIN = 0; }else{ chngToIN &= b; } } @@ -1509,19 +1005,19 @@ ** and column is found but leave okToChngToIN false if not found. */ for(j=0; j<2 && !okToChngToIN; j++){ pOrTerm = pOrWc->a; for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){ - assert( pOrTerm->eOperator & WO_EQ ); + assert( pOrTerm->eOperator==WO_EQ ); pOrTerm->wtFlags &= ~TERM_OR_OK; if( pOrTerm->leftCursor==iCursor ){ /* This is the 2-bit case and we are on the second iteration and ** current term is from the first iteration. So skip this term. */ assert( j==1 ); continue; } - if( (chngToIN & getMask(&pWInfo->sMaskSet, pOrTerm->leftCursor))==0 ){ + if( (chngToIN & getMask(pMaskSet, pOrTerm->leftCursor))==0 ){ /* This term must be of the form t1.a==t2.b where t2 is in the ** chngToIN set but t1 is not. This term will be either preceeded ** or follwed by an inverted copy (t2.b==t1.a). Skip this term ** and use its inversion. */ testcase( pOrTerm->wtFlags & TERM_COPIED ); @@ -1535,21 +1031,21 @@ } if( i<0 ){ /* No candidate table+column was found. This can only occur ** on the second iteration */ assert( j==1 ); - assert( IsPowerOfTwo(chngToIN) ); - assert( chngToIN==getMask(&pWInfo->sMaskSet, iCursor) ); + assert( (chngToIN&(chngToIN-1))==0 ); + assert( chngToIN==getMask(pMaskSet, iCursor) ); break; } testcase( j==1 ); /* We have found a candidate table and column. Check to see if that ** table and column is common to every term in the OR clause */ okToChngToIN = 1; for(; i>=0 && okToChngToIN; i--, pOrTerm++){ - assert( pOrTerm->eOperator & WO_EQ ); + assert( pOrTerm->eOperator==WO_EQ ); if( pOrTerm->leftCursor!=iCursor ){ pOrTerm->wtFlags &= ~TERM_OR_OK; }else if( pOrTerm->u.leftColumn!=iColumn ){ okToChngToIN = 0; }else{ @@ -1581,15 +1077,15 @@ Expr *pLeft = 0; /* The LHS of the IN operator */ Expr *pNew; /* The complete IN operator */ for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){ if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue; - assert( pOrTerm->eOperator & WO_EQ ); + assert( pOrTerm->eOperator==WO_EQ ); assert( pOrTerm->leftCursor==iCursor ); assert( pOrTerm->u.leftColumn==iColumn ); pDup = sqlite4ExprDup(db, pOrTerm->pExpr->pRight, 0); - pList = sqlite4ExprListAppend(pWInfo->pParse, pList, pDup); + pList = sqlite4ExprListAppend(pWC->pParse, pList, pDup); pLeft = pOrTerm->pExpr->pLeft; } assert( pLeft!=0 ); pDup = sqlite4ExprDup(db, pLeft, 0); pNew = sqlite4PExpr(pParse, TK_IN, pDup, 0, 0); @@ -1610,10 +1106,11 @@ pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */ } } } #endif /* !SQLITE4_OMIT_OR_OPTIMIZATION && !SQLITE4_OMIT_SUBQUERY */ + /* ** The input to this routine is an WhereTerm structure with only the ** "pExpr" field filled in. The job of this routine is to analyze the ** subexpression and populate all the other fields of the WhereTerm @@ -1634,11 +1131,10 @@ static void exprAnalyze( SrcList *pSrc, /* the FROM clause */ WhereClause *pWC, /* the WHERE clause */ int idxTerm /* Index of the term to be analyzed */ ){ - WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */ WhereTerm *pTerm; /* The term to be analyzed */ WhereMaskSet *pMaskSet; /* Set of table index masks */ Expr *pExpr; /* The expression to be analyzed */ Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */ Bitmask prereqAll; /* Prerequesites of pExpr */ @@ -1645,20 +1141,19 @@ Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */ Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */ int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */ int noCase = 0; /* LIKE/GLOB distinguishes case */ int op; /* Top-level operator. pExpr->op */ - Parse *pParse = pWInfo->pParse; /* Parsing context */ + Parse *pParse = pWC->pParse; /* Parsing context */ sqlite4 *db = pParse->db; /* Database connection */ if( db->mallocFailed ){ return; } pTerm = &pWC->a[idxTerm]; - pMaskSet = &pWInfo->sMaskSet; + pMaskSet = pWC->pMaskSet; pExpr = pTerm->pExpr; - assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); op = pExpr->op; if( op==TK_IN ){ assert( pExpr->pRight==0 ); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ @@ -1680,23 +1175,21 @@ } pTerm->prereqAll = prereqAll; pTerm->leftCursor = -1; pTerm->iParent = -1; pTerm->eOperator = 0; - if( allowedOp(op) ){ - Expr *pLeft = sqlite4ExprSkipCollate(pExpr->pLeft); - Expr *pRight = sqlite4ExprSkipCollate(pExpr->pRight); - u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV; + if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){ + Expr *pLeft = pExpr->pLeft; + Expr *pRight = pExpr->pRight; if( pLeft->op==TK_COLUMN ){ pTerm->leftCursor = pLeft->iTable; pTerm->u.leftColumn = pLeft->iColumn; - pTerm->eOperator = operatorMask(op) & opMask; + pTerm->eOperator = operatorMask(op); } if( pRight && pRight->op==TK_COLUMN ){ WhereTerm *pNew; Expr *pDup; - u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */ if( pTerm->leftCursor>=0 ){ int idxNew; pDup = sqlite4ExprDup(db, pExpr, 0); if( db->mallocFailed ){ sqlite4ExprDelete(db, pDup); @@ -1707,29 +1200,22 @@ pNew = &pWC->a[idxNew]; pNew->iParent = idxTerm; pTerm = &pWC->a[idxTerm]; pTerm->nChild = 1; pTerm->wtFlags |= TERM_COPIED; - if( pExpr->op==TK_EQ - && !ExprHasProperty(pExpr, EP_FromJoin) - && OptimizationEnabled(db, SQLITE4_Transitive) - ){ - pTerm->eOperator |= WO_EQUIV; - eExtraOp = WO_EQUIV; - } }else{ pDup = pExpr; pNew = pTerm; } exprCommute(pParse, pDup); - pLeft = sqlite4ExprSkipCollate(pDup->pLeft); + pLeft = pDup->pLeft; pNew->leftCursor = pLeft->iTable; pNew->u.leftColumn = pLeft->iColumn; testcase( (prereqLeft | extraRight) != prereqLeft ); pNew->prereqRight = prereqLeft | extraRight; pNew->prereqAll = prereqAll; - pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask; + pNew->eOperator = operatorMask(pDup->op); } } #ifndef SQLITE4_OMIT_BETWEEN_OPTIMIZATION /* If a term is the BETWEEN operator, create two new virtual terms @@ -1798,11 +1284,11 @@ Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */ Expr *pNewExpr1; Expr *pNewExpr2; int idxNew1; int idxNew2; - Token sCollSeqName; /* Name of collating sequence */ + CollSeq *pColl; /* Collating sequence to use */ pLeft = pExpr->x.pList->a[1].pExpr; pStr2 = sqlite4ExprDup(db, pStr1, 0); if( !db->mallocFailed ){ u8 c, *pC; /* Last character before the first wildcard */ @@ -1820,21 +1306,20 @@ c = sqlite4UpperToLower[c]; } *pC = c + 1; } - sCollSeqName.z = noCase ? "NOCASE" : "BINARY"; - sCollSeqName.n = 6; - pNewExpr1 = sqlite4ExprDup(db, pLeft, 0); - sqlite4ExprSetCollByToken(pParse, pNewExpr1, &sCollSeqName); - pNewExpr1 = sqlite4PExpr(pParse, TK_GE, pNewExpr1, pStr1, 0); + pColl = sqlite4FindCollSeq(db, noCase ? "NOCASE" : "BINARY",0); + pNewExpr1 = sqlite4PExpr(pParse, TK_GE, + sqlite4ExprSetColl(sqlite4ExprDup(db,pLeft,0), pColl), + pStr1, 0); idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew1==0 ); exprAnalyze(pSrc, pWC, idxNew1); - pNewExpr2 = sqlite4ExprDup(db, pLeft, 0); - sqlite4ExprSetCollByToken(pParse, pNewExpr2, &sCollSeqName); - pNewExpr2 = sqlite4PExpr(pParse, TK_LT, pNewExpr2, pStr2, 0); + pNewExpr2 = sqlite4PExpr(pParse, TK_LT, + sqlite4ExprSetColl(sqlite4ExprDup(db,pLeft,0), pColl), + pStr2, 0); idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew2==0 ); exprAnalyze(pSrc, pWC, idxNew2); pTerm = &pWC->a[idxTerm]; if( isComplete ){ @@ -1894,11 +1379,10 @@ ** the start of the loop will prevent any results from being returned. */ if( pExpr->op==TK_NOTNULL && pExpr->pLeft->op==TK_COLUMN && pExpr->pLeft->iColumn>=0 - && OptimizationEnabled(db, SQLITE4_Stat3) ){ Expr *pNewExpr; Expr *pLeft = pExpr->pLeft; int idxNew; WhereTerm *pNewTerm; @@ -1929,12 +1413,34 @@ */ pTerm->prereqRight |= extraRight; } /* -** This function searches pList for a entry that matches the iCol-th column -** of index pIdx. +** Return TRUE if any of the expressions in pList->a[iFirst...] contain +** a reference to any table other than the iBase table. +*/ +static int referencesOtherTables( + ExprList *pList, /* Search expressions in ths list */ + WhereMaskSet *pMaskSet, /* Mapping from tables to bitmaps */ + int iFirst, /* Be searching with the iFirst-th expression */ + int iBase /* Ignore references to this table */ +){ + Bitmask allowed = ~getMask(pMaskSet, iBase); + while( iFirstnExpr ){ + if( (exprTableUsage(pMaskSet, pList->a[iFirst++].pExpr)&allowed)!=0 ){ + return 1; + } + } + return 0; +} + +/* +** This function searches the expression list passed as the second argument +** for an expression of type TK_COLUMN that refers to the same column and +** uses the same collation sequence as the iCol'th column of index pIdx. +** Argument iBase is the cursor number used for the table that pIdx refers +** to. ** ** If such an expression is found, its index in pList->a[] is returned. If ** no expression is found, -1 is returned. */ static int findIndexCol( @@ -1946,37 +1452,96 @@ ){ int i; const char *zColl = pIdx->azColl[iCol]; for(i=0; inExpr; i++){ - Expr *p = sqlite4ExprSkipCollate(pList->a[i].pExpr); + Expr *p = pList->a[i].pExpr; if( p->op==TK_COLUMN && p->iColumn==pIdx->aiColumn[iCol] && p->iTable==iBase ){ - CollSeq *pColl = sqlite4ExprCollSeq(pParse, pList->a[i].pExpr); - if( ALWAYS(pColl) && 0==sqlite4_stricmp(pColl->zName, zColl) ){ + CollSeq *pColl = sqlite4ExprCollSeq(pParse, p); + assert( pColl || p->iColumn==-1 ); + if( 0==pColl || 0==sqlite4_stricmp(pColl->zName, zColl) ){ return i; } } } return -1; } + +/* +** This routine determines if pIdx can be used to assist in processing a +** DISTINCT qualifier. In other words, it tests whether or not using this +** index for the outer loop guarantees that rows with equal values for +** all expressions in the pDistinct list are delivered grouped together. +** +** For example, the query +** +** SELECT DISTINCT a, b, c FROM tbl WHERE a = ? +** +** can benefit from any index on columns "b" and "c". +*/ +static int isDistinctIndex( + Parse *pParse, /* Parsing context */ + WhereClause *pWC, /* The WHERE clause */ + Index *pIdx, /* The index being considered */ + int base, /* Cursor number for the table pIdx is on */ + ExprList *pDistinct, /* The DISTINCT expressions */ + int nEqCol /* Number of index columns with == */ +){ + Bitmask mask = 0; /* Mask of unaccounted for pDistinct exprs */ + int i; /* Iterator variable */ + + if( pIdx->zName==0 || pDistinct==0 || pDistinct->nExpr>=BMS ) return 0; + testcase( pDistinct->nExpr==BMS-1 ); + + /* Loop through all the expressions in the distinct list. If any of them + ** are not simple column references, return early. Otherwise, test if the + ** WHERE clause contains a "col=X" clause. If it does, the expression + ** can be ignored. If it does not, and the column does not belong to the + ** same table as index pIdx, return early. Finally, if there is no + ** matching "col=X" expression and the column is on the same table as pIdx, + ** set the corresponding bit in variable mask. + */ + for(i=0; inExpr; i++){ + WhereTerm *pTerm; + Expr *p = pDistinct->a[i].pExpr; + if( p->op!=TK_COLUMN ) return 0; + pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0); + if( pTerm ){ + Expr *pX = pTerm->pExpr; + CollSeq *p1 = sqlite4BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); + CollSeq *p2 = sqlite4ExprCollSeq(pParse, p); + if( p1==p2 ) continue; + } + if( p->iTable!=base ) return 0; + mask |= (((Bitmask)1) << i); + } + + for(i=nEqCol; mask && inColumn; i++){ + int iExpr = findIndexCol(pParse, pDistinct, base, pIdx, i); + if( iExpr<0 ) break; + mask &= ~(((Bitmask)1) << iExpr); + } + + return (mask==0); +} + /* ** Return true if the DISTINCT expression-list passed as the third argument -** is redundant. -** -** A DISTINCT list is redundant if the database contains some subset of -** columns that are unique and non-null. +** is redundant. A DISTINCT list is redundant if the database contains a +** UNIQUE index that guarantees that the result of the query will be distinct +** anyway. */ static int isDistinctRedundant( - Parse *pParse, /* Parsing context */ - SrcList *pTabList, /* The FROM clause */ - WhereClause *pWC, /* The WHERE clause */ - ExprList *pDistinct /* The result set that needs to be DISTINCT */ + Parse *pParse, + SrcList *pTabList, + WhereClause *pWC, + ExprList *pDistinct ){ Table *pTab; Index *pIdx; int i; int iBase; @@ -1991,11 +1556,11 @@ /* If any of the expressions is an IPK column on table iBase, then return ** true. Note: The (p->iTable==iBase) part of this test may be false if the ** current SELECT is a correlated sub-query. */ for(i=0; inExpr; i++){ - Expr *p = sqlite4ExprSkipCollate(pDistinct->a[i].pExpr); + Expr *p = pDistinct->a[i].pExpr; if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1; } /* Loop through all indices on the table, checking each to see if it makes ** the DISTINCT qualifier redundant. It does so if: @@ -2004,23 +1569,19 @@ ** ** 2. All of the columns in the index are either part of the pDistinct ** list, or else the WHERE clause contains a term of the form "col=X", ** where X is a constant value. The collation sequences of the ** comparison and select-list expressions must match those of the index. - ** - ** 3. All of those index columns for which the WHERE clause does not - ** contain a "col=X" term are subject to a NOT NULL constraint. */ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( pIdx->onError==OE_None ) continue; for(i=0; inColumn; i++){ int iCol = pIdx->aiColumn[i]; - if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx) ){ - int iIdxCol = findIndexCol(pParse, pDistinct, iBase, pIdx, i); - if( iIdxCol<0 || pTab->aCol[pIdx->aiColumn[i]].notNull==0 ){ - break; - } + if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx) + && 0>findIndexCol(pParse, pDistinct, iBase, pIdx, i) + ){ + break; } } if( i==pIdx->nColumn ){ /* This index implies that the DISTINCT qualifier is redundant. */ return 1; @@ -2028,89 +1589,228 @@ } return 0; } -/* -** The (an approximate) sum of two WhereCosts. This computation is -** not a simple "+" operator because WhereCost is stored as a logarithmic -** value. -** -*/ -static WhereCost whereCostAdd(WhereCost a, WhereCost b){ - static const unsigned char x[] = { - 10, 10, /* 0,1 */ - 9, 9, /* 2,3 */ - 8, 8, /* 4,5 */ - 7, 7, 7, /* 6,7,8 */ - 6, 6, 6, /* 9,10,11 */ - 5, 5, 5, /* 12-14 */ - 4, 4, 4, 4, /* 15-18 */ - 3, 3, 3, 3, 3, 3, /* 19-24 */ - 2, 2, 2, 2, 2, 2, 2, /* 25-31 */ - }; - if( a>=b ){ - if( a>b+49 ) return a; - if( a>b+31 ) return a+1; - return a+x[a-b]; - }else{ - if( b>a+49 ) return b; - if( b>a+31 ) return b+1; - return b+x[b-a]; - } -} - -/* -** Convert an integer into a WhereCost. In other words, compute a -** good approximatation for 10*log2(x). -*/ -static WhereCost whereCost(tRowcnt x){ - static WhereCost a[] = { 0, 2, 3, 5, 6, 7, 8, 9 }; - WhereCost y = 40; - if( x<8 ){ - if( x<2 ) return 0; - while( x<8 ){ y -= 10; x <<= 1; } - }else{ - while( x>255 ){ y += 40; x >>= 4; } - while( x>15 ){ y += 10; x >>= 1; } - } - return a[x&7] + y - 10; -} - -#ifndef SQLITE4_OMIT_VIRTUALTABLE -/* -** Convert a double (as received from xBestIndex of a virtual table) -** into a WhereCost. In other words, compute an approximation for -** 10*log2(x). -*/ -static WhereCost whereCostFromDouble(double x){ - u64 a; - WhereCost e; - assert( sizeof(x)==8 && sizeof(a)==8 ); - if( x<=1 ) return 0; - if( x<=2000000000 ) return whereCost((tRowcnt)x); - memcpy(&a, &x, 8); - e = (a>>52) - 1022; - return e*10; -} -#endif /* SQLITE4_OMIT_VIRTUALTABLE */ - -/* -** Estimate the logarithm of the input value to base 2. -*/ -static WhereCost estLog(WhereCost N){ - WhereCost x = whereCost(N); - return x>33 ? x - 33 : 0; + +/* +** Return the table column number of the iIdxCol'th field in the index +** keys used by index pIdx, including any appended PRIMARY KEY fields. +** If there is no iIdxCol'th field in index pIdx, return -2. +** +** Example: +** +** CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b)); +** CREATE INDEX i1 ON t1(c); +** +** Index i1 in the example above consists of three fields - the indexed +** field "c" followed by the two primary key fields. The automatic PRIMARY +** KEY index consists of two fields only. +*/ +static int idxColumnNumber(Index *pIdx, Index *pPk, int iIdxCol){ + int iRet = -2; + if( iIdxColnColumn ){ + iRet = pIdx->aiColumn[iIdxCol]; + }else if( pPk && iIdxCol<(pIdx->nColumn + pPk->nColumn) ){ + iRet = pPk->aiColumn[iIdxCol - pIdx->nColumn]; + } + return iRet; +} + +/* +** Return the name of the iCol'th column of table pTab. Or, if iCol is less +** than zero, return a pointer to the constant string "rowid". +*/ +static const char *tblColumnName(Table *pTab, int iCol){ + if( iCol<0 ) return "rowid"; + return pTab->aCol[iCol].zName; +} + +/* +** This routine decides if pIdx can be used to satisfy the ORDER BY +** clause. If it can, it returns 1. If pIdx cannot satisfy the +** ORDER BY clause, this routine returns 0. +** +** pOrderBy is an ORDER BY clause from a SELECT statement. pTab is the +** left-most table in the FROM clause of that same SELECT statement and +** the table has a cursor number of "base". pIdx is an index on pTab. +** +** nEqCol is the number of columns of pIdx that are used as equality +** constraints. Any of these columns may be missing from the ORDER BY +** clause and the match can still be a success. +** +** All terms of the ORDER BY that match against the index must be either +** ASC or DESC. (Terms of the ORDER BY clause past the end of a UNIQUE +** index do not need to satisfy this constraint.) The *pbRev value is +** set to 1 if the ORDER BY clause is all DESC and it is set to 0 if +** the ORDER BY clause is all ASC. +*/ +static int isSortingIndex( + Parse *pParse, /* Parsing context */ + WhereMaskSet *pMaskSet, /* Mapping from table cursor numbers to bitmaps */ + Index *pIdx, /* The index we are testing */ + int base, /* Cursor number for the table to be sorted */ + ExprList *pOrderBy, /* The ORDER BY clause */ + int nEqCol, /* Number of index columns with == constraints */ + int wsFlags, /* Index usages flags */ + int *pbRev /* Set to 1 if ORDER BY is DESC */ +){ + sqlite4 *db = pParse->db; /* Database handle */ + int sortOrder = 0; /* XOR of index and ORDER BY sort direction */ + int nTerm; /* Number of ORDER BY terms */ + int iTerm; /* Used to iterate through nTerm terms */ + int iNext = nEqCol; /* Index of next unmatched column in index */ + int nIdxCol; /* Number of columns in index, incl. PK */ + Index *pPk; + Table *pTab; + + if( !pOrderBy ) return 0; + if( wsFlags & WHERE_COLUMN_IN ) return 0; + if( pIdx->fIndex & IDX_Unordered ) return 0; + + pTab = pIdx->pTable; + pPk = sqlite4FindPrimaryKey(pTab, 0); + nTerm = pOrderBy->nExpr; + nIdxCol = pIdx->nColumn + (pIdx==pPk ? 0 : pPk->nColumn); + + assert( nTerm>0 ); + assert( pIdx && pIdx->zName ); + + for(iTerm=0; iTerma[iTerm]; + pExpr = pTerm->pExpr; + if( pExpr->op!=TK_COLUMN || pExpr->iTable!=base ) break; + iColumn = pExpr->iColumn; + + /* Check that column iColumn is a part of the index. If it is not, then + ** this index may not be used as a sorting index. This block also checks + ** that column iColumn is either the iNext'th column of the index, or + ** else one of the nEqCol columns that the index guarantees will be + ** constant. */ + for(iIdxCol=0; iIdxCol=nEqCol && iIdxCol!=iNext) ) break; + + /* Check that the collation sequence used by the expression is the same + ** as the collation sequence used by the index. If not, this is not a + ** sorting index. */ + pColl = sqlite4ExprCollSeq(pParse, pExpr); + if( !pColl ) pColl = db->pDfltColl; + if( iIdxColnColumn ){ + zColl = pIdx->azColl[iIdxCol]; + }else if( iColumn>=0 ) { + zColl = pTab->aCol[iColumn].zColl; + }else{ + zColl = 0; + } + if( pColl!=sqlite4FindCollSeq(db, zColl, 0) ) break; + + if( iIdxCol==iNext ){ + u8 reqSortOrder; + u8 idxSortOrder = SQLITE4_SO_ASC; + if( iIdxColnColumn ) idxSortOrder = pIdx->aSortOrder[iIdxCol]; + assert( idxSortOrder==SQLITE4_SO_ASC || idxSortOrder==SQLITE4_SO_DESC ); + + reqSortOrder = (idxSortOrder ^ pTerm->sortOrder); + if( iNext==nEqCol ){ + sortOrder = reqSortOrder; + }else if( sortOrder!=reqSortOrder ){ + break; + } + iNext++; + } + +#if 0 + if( iColumn<0 && !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){ + /* If the indexed column is the primary key and everything matches + ** so far and none of the ORDER BY terms to the right reference other + ** tables in the join, then we are assured that the index can be used + ** to sort because the primary key is unique and so none of the other + ** columns will make any difference + */ + j = nTerm; + } +#endif + } + + *pbRev = sortOrder!=0; + + if( iTerm>=nTerm ){ + /* All terms of the ORDER BY clause are covered by this index. The + ** index can therefore be used for sorting. */ + return 1; + } + + if( pIdx->onError!=OE_None + && iNext>=pIdx->nColumn + && (wsFlags & WHERE_COLUMN_NULL)==0 + && !referencesOtherTables(pOrderBy, pMaskSet, iTerm, base) + ){ + + if( iNext==nIdxCol ){ + /* All columns indexed by this UNIQUE index, and all PK columns are + ** are matched by a prefix of the ORDER BY clause. And since the PK + ** columns are guaranteed to be unique and NOT NULL, there is no way + ** for the trailing ORDER BY terms to affect the sort order. Therefore, + ** we have a sorting index. */ + return 1; + }else{ + int i; + for(i=nEqCol; inColumn; i++){ + int iCol = pIdx->aiColumn[i]; + if( iCol>=0 && pTab->aCol[iCol].notNull==0 ) break; + } + + /* All columns indexed by this UNIQUE index are matched by a prefix + ** of the ORDER BY clause. And there is reason to believe that none + ** of the expressions in the ORDER BY prefix will evalulate to NULL. + ** The index may be used for sorting in this case too since it is + ** guaranteed that none of the trailing, unmatched ORDER BY terms + ** affect the sort order. */ + return (i>=pIdx->nColumn); + } + } + + return 0; +} + +/* +** Prepare a crude estimate of the logarithm of the input value. +** The results need not be exact. This is only used for estimating +** the total cost of performing operations with O(logN) or O(NlogN) +** complexity. Because N is just a guess, it is no great tragedy if +** logN is a little off. +*/ +static double estLog(double N){ + double logN = 1; + double x = 10; + while( N>x ){ + logN += 1; + x *= 10; + } + return logN; } /* ** Two routines for printing the content of an sqlite4_index_info ** structure. Used for testing and debugging only. If neither ** SQLITE4_TEST or SQLITE4_DEBUG are defined, then these routines ** are no-ops. */ -#if !defined(SQLITE4_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED) +#if !defined(SQLITE4_OMIT_VIRTUALTABLE) && defined(SQLITE4_DEBUG) static void TRACE_IDX_INPUTS(sqlite4_index_info *p){ int i; if( !sqlite4WhereTrace ) return; for(i=0; inConstraint; i++){ sqlite4DebugPrintf(" constraint[%d]: col=%d termid=%d op=%d usabled=%d\n", @@ -2143,33 +1843,212 @@ } #else #define TRACE_IDX_INPUTS(A) #define TRACE_IDX_OUTPUTS(A) #endif + +/* +** Required because bestIndex() is called by bestOrClauseIndex() +*/ +static void bestIndex( + Parse*, WhereClause*, SrcListItem*, + Bitmask, Bitmask, ExprList*, WhereCost*); + +/* +** This routine attempts to find an scanning strategy that can be used +** to optimize an 'OR' expression that is part of a WHERE clause. +** +** The table associated with FROM clause term pSrc may be either a +** regular B-Tree table or a virtual table. +*/ +static void bestOrClauseIndex( + Parse *pParse, /* The parsing context */ + WhereClause *pWC, /* The WHERE clause */ + SrcListItem *pSrc, /* The FROM clause term to search */ + Bitmask notReady, /* Mask of cursors not available for indexing */ + Bitmask notValid, /* Cursors not available for any purpose */ + ExprList *pOrderBy, /* The ORDER BY clause */ + WhereCost *pCost /* Lowest cost query plan */ +){ +#ifndef SQLITE4_OMIT_OR_OPTIMIZATION + const int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */ + const Bitmask maskSrc = getMask(pWC->pMaskSet, iCur); /* Bitmask for pSrc */ + WhereTerm * const pWCEnd = &pWC->a[pWC->nTerm]; /* End of pWC->a[] */ + WhereTerm *pTerm; /* A single term of the WHERE clause */ + + /* The OR-clause optimization is disallowed if the INDEXED BY or + ** NOT INDEXED clauses are used or if the WHERE_AND_ONLY bit is set. */ + if( pSrc->notIndexed || pSrc->pIndex!=0 ){ + return; + } + if( pWC->wctrlFlags & WHERE_AND_ONLY ){ + return; + } + + /* Search the WHERE clause terms for a usable WO_OR term. */ + for(pTerm=pWC->a; pTermeOperator==WO_OR + && ((pTerm->prereqAll & ~maskSrc) & notReady)==0 + && (pTerm->u.pOrInfo->indexable & maskSrc)!=0 + ){ + WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; + WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; + WhereTerm *pOrTerm; + int flags = WHERE_MULTI_OR; + double rTotal = 0; + double nRow = 0; + Bitmask used = 0; + + for(pOrTerm=pOrWC->a; pOrTerma), (pTerm - pWC->a) + )); + if( pOrTerm->eOperator==WO_AND ){ + WhereClause *pAndWC = &pOrTerm->u.pAndInfo->wc; + bestIndex(pParse, pAndWC, pSrc, notReady, notValid, 0, &sTermCost); + }else if( pOrTerm->leftCursor==iCur ){ + WhereClause tempWC; + tempWC.pParse = pWC->pParse; + tempWC.pMaskSet = pWC->pMaskSet; + tempWC.pOuter = pWC; + tempWC.op = TK_AND; + tempWC.a = pOrTerm; + tempWC.wctrlFlags = 0; + tempWC.nTerm = 1; + bestIndex(pParse, &tempWC, pSrc, notReady, notValid, 0, &sTermCost); + }else{ + continue; + } + rTotal += sTermCost.rCost; + nRow += sTermCost.plan.nRow; + used |= sTermCost.used; + if( rTotal>=pCost->rCost ) break; + } + + /* If there is an ORDER BY clause, increase the scan cost to account + ** for the cost of the sort. */ + if( pOrderBy!=0 ){ + WHERETRACE(("... sorting increases OR cost %.9g to %.9g\n", + rTotal, rTotal+nRow*estLog(nRow))); + rTotal += nRow*estLog(nRow); + } + + /* If the cost of scanning using this OR term for optimization is + ** less than the current cost stored in pCost, replace the contents + ** of pCost. */ + WHERETRACE(("... multi-index OR cost=%.9g nrow=%.9g\n", rTotal, nRow)); + if( rTotalrCost ){ + pCost->rCost = rTotal; + pCost->used = used; + pCost->plan.nRow = nRow; + pCost->plan.wsFlags = flags; + pCost->plan.u.pTerm = pTerm; + } + } + } +#endif /* SQLITE4_OMIT_OR_OPTIMIZATION */ +} #ifndef SQLITE4_OMIT_AUTOMATIC_INDEX /* ** Return TRUE if the WHERE clause term pTerm is of a form where it ** could be used with an index to access pSrc, assuming an appropriate ** index existed. */ static int termCanDriveIndex( WhereTerm *pTerm, /* WHERE clause term to check */ - struct SrcListItem *pSrc, /* Table we are trying to access */ + SrcListItem *pSrc, /* Table we are trying to access */ Bitmask notReady /* Tables in outer loops of the join */ ){ char aff; if( pTerm->leftCursor!=pSrc->iCursor ) return 0; - if( (pTerm->eOperator & WO_EQ)==0 ) return 0; + if( pTerm->eOperator!=WO_EQ ) return 0; if( (pTerm->prereqRight & notReady)!=0 ) return 0; - if( pTerm->u.leftColumn<0 ) return 0; aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity; if( !sqlite4IndexAffinityOk(pTerm->pExpr, aff) ) return 0; return 1; } #endif +#ifndef SQLITE4_OMIT_AUTOMATIC_INDEX +/* +** If the query plan for pSrc specified in pCost is a full table scan +** and indexing is allows (if there is no NOT INDEXED clause) and it +** possible to construct a transient index that would perform better +** than a full table scan even when the cost of constructing the index +** is taken into account, then alter the query plan to use the +** transient index. +*/ +static void bestAutomaticIndex( + Parse *pParse, /* The parsing context */ + WhereClause *pWC, /* The WHERE clause */ + SrcListItem *pSrc, /* The FROM clause term to search */ + Bitmask notReady, /* Mask of cursors that are not available */ + WhereCost *pCost /* Lowest cost query plan */ +){ + double nTableRow; /* Rows in the input table */ + double logN; /* log(nTableRow) */ + double costTempIdx; /* per-query cost of the transient index */ + WhereTerm *pTerm; /* A single term of the WHERE clause */ + WhereTerm *pWCEnd; /* End of pWC->a[] */ + Table *pTable; /* Table tht might be indexed */ + + if( pParse->nQueryLoop<=(double)1 ){ + /* There is no point in building an automatic index for a single scan */ + return; + } + if( (pParse->db->flags & SQLITE4_AutoIndex)==0 ){ + /* Automatic indices are disabled at run-time */ + return; + } + if( (pWC->wctrlFlags & WHERE_NO_AUTOINDEX)!=0 ){ + return; + } + if( (pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 ){ + /* We already have some kind of index in use for this query. */ + return; + } + if( pSrc->notIndexed ){ + /* The NOT INDEXED clause appears in the SQL. */ + return; + } + if( pSrc->isCorrelated ){ + /* The source is a correlated sub-query. No point in indexing it. */ + return; + } + + assert( pParse->nQueryLoop >= (double)1 ); + pTable = pSrc->pTab; + nTableRow = pTable->nRowEst; + logN = estLog(nTableRow); + costTempIdx = 2*logN*(nTableRow/pParse->nQueryLoop + 1); + if( costTempIdx>=pCost->rCost ){ + /* The cost of creating the transient table would be greater than + ** doing the full table scan */ + return; + } + + /* Search for any equality comparison term */ + pWCEnd = &pWC->a[pWC->nTerm]; + for(pTerm=pWC->a; pTermrCost, costTempIdx)); + pCost->rCost = costTempIdx; + pCost->plan.nRow = logN + 1; + pCost->plan.wsFlags = WHERE_TEMP_INDEX; + pCost->plan.u.pIdx = 0; + pCost->used = pTerm->prereqRight; + break; + } + } +} +#else +# define bestAutomaticIndex(A,B,C,D,E) /* no-op */ +#endif /* SQLITE4_OMIT_AUTOMATIC_INDEX */ + #ifndef SQLITE4_OMIT_AUTOMATIC_INDEX /* ** Generate code to construct the Index object for an automatic index ** and to set up the WhereLevel object pLevel so that the code generator @@ -2176,118 +2055,80 @@ ** makes use of the automatic index. */ static void constructAutomaticIndex( Parse *pParse, /* The parsing context */ WhereClause *pWC, /* The WHERE clause */ - struct SrcListItem *pSrc, /* The FROM clause term to get the next index */ + SrcListItem *pSrc, /* The FROM clause term to get the next index */ Bitmask notReady, /* Mask of cursors that are not available */ WhereLevel *pLevel /* Write new index here */ ){ - int nColumn; /* Number of columns in the constructed index */ + int nCol = 0; /* Number of columns in index keys */ WhereTerm *pTerm; /* A single term of the WHERE clause */ WhereTerm *pWCEnd; /* End of pWC->a[] */ int nByte; /* Byte of memory needed for pIdx */ Index *pIdx; /* Object describing the transient index */ Vdbe *v; /* Prepared statement under construction */ - int addrInit; /* Address of the initialization bypass jump */ + int addrOnce; /* Address of the initialization bypass jump */ Table *pTable; /* The table being indexed */ KeyInfo *pKeyinfo; /* Key information for the index */ - int addrTop; /* Top of the index fill loop */ - int regRecord; /* Register holding an index value */ + int addrRewind; /* Top of the index fill loop */ + int regRecord; /* Register holding an index record */ int regKey; /* Register holding an index key */ int n; /* Column counter */ - int i; /* Loop counter */ - int mxBitCol; /* Maximum column in pSrc->colUsed */ - int iPkCsr; /* PK cursor number */ CollSeq *pColl; /* Collating sequence to on a column */ - WhereLoop *pLoop; /* The Loop object */ Bitmask idxCols; /* Bitmap of columns used for indexing */ - Bitmask extraCols; /* Bitmap of additional columns */ - u8 sentWarning = 0; /* True if a warnning has been issued */ + int iPkCur = pLevel->iTabCur; /* Primary key cursor to read data from */ /* Generate code to skip over the creation and initialization of the ** transient index on 2nd and subsequent iterations of the loop. */ v = pParse->pVdbe; assert( v!=0 ); - addrInit = sqlite4CodeOnce(pParse); + addrOnce = sqlite4CodeOnce(pParse); - /* Count the number of columns that will be added to the index - ** and used to match WHERE clause constraints */ - nColumn = 0; + /* Count the number of columns that will be encoded into the index keys. + ** set nCol to this value. Use the idxCols mask to ensure that the same + ** column is not added to the index more than once. */ pTable = pSrc->pTab; pWCEnd = &pWC->a[pWC->nTerm]; - pLoop = pLevel->pWLoop; idxCols = 0; for(pTerm=pWC->a; pTermu.leftColumn; - Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); + Bitmask cMask = iCol>=BMS ? ((Bitmask)1)<<(BMS-1) : ((Bitmask)1)<db->pEnv, SQLITE4_WARNING_AUTOINDEX, - "automatic index on %s(%s)", pTable->zName, - pTable->aCol[iCol].zName); - sentWarning = 1; - } if( (idxCols & cMask)==0 ){ - if( whereLoopResize(pParse->db, pLoop, nColumn+1) ) return; - pLoop->aLTerm[nColumn++] = pTerm; + nCol++; idxCols |= cMask; } } } - assert( nColumn>0 ); - pLoop->u.btree.nEq = pLoop->nLTerm = nColumn; - pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED - | WHERE_AUTO_INDEX; - - /* Count the number of additional columns needed to create a - ** covering index. A "covering index" is an index that contains all - ** columns that are needed by the query. With a covering index, the - ** original table never needs to be accessed. Automatic indices must - ** be a covering index because the index will not be updated if the - ** original table changes and the index and table cannot both be used - ** if they go out of sync. - */ - extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1)); - mxBitCol = (pTable->nCol >= BMS-1) ? BMS-1 : pTable->nCol; - testcase( pTable->nCol==BMS-1 ); - testcase( pTable->nCol==BMS-2 ); - for(i=0; icolUsed & MASKBIT(BMS-1) ){ - nColumn += pTable->nCol - BMS + 1; - } - pLoop->wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY; + assert( nCol>0 ); + pLevel->plan.nEq = nCol; + pLevel->plan.wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WO_EQ; /* Construct the Index object to describe this index */ - nByte = sizeof(Index); - nByte += nColumn*sizeof(int); /* Index.aiColumn */ - nByte += nColumn*sizeof(char*); /* Index.azColl */ - nByte += nColumn; /* Index.aSortOrder */ + nByte = sizeof(Index); /* Index */ + nByte += nCol*sizeof(int); /* Index.aiColumn */ + nByte += nCol*sizeof(char*); /* Index.azColl */ + nByte += nCol; /* Index.aSortOrder */ pIdx = sqlite4DbMallocZero(pParse->db, nByte); if( pIdx==0 ) return; - pLoop->u.btree.pIndex = pIdx; + pLevel->plan.u.pIdx = pIdx; + pIdx->eIndexType = SQLITE4_INDEX_TEMP; pIdx->azColl = (char**)&pIdx[1]; - pIdx->aiColumn = (int*)&pIdx->azColl[nColumn]; - pIdx->aSortOrder = (u8*)&pIdx->aiColumn[nColumn]; + pIdx->aiColumn = (int*)&pIdx->azColl[nCol]; + pIdx->aSortOrder = (u8*)&pIdx->aiColumn[nCol]; pIdx->zName = "auto-index"; - pIdx->nColumn = nColumn; + pIdx->nColumn = nCol; pIdx->pTable = pTable; - pIdx->aiCover = pIdx->aiColumn; - pIdx->nCover = pIdx->nColumn; - pIdx->eIndexType = SQLITE4_INDEX_TEMP; n = 0; idxCols = 0; for(pTerm=pWC->a; pTermu.leftColumn; - Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); - testcase( iCol==BMS-1 ); - testcase( iCol==BMS ); + Bitmask cMask = iCol>=BMS ? ((Bitmask)1)<<(BMS-1) : ((Bitmask)1)<pExpr; idxCols |= cMask; pIdx->aiColumn[n] = pTerm->u.leftColumn; pColl = sqlite4BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); @@ -2294,54 +2135,33 @@ pIdx->azColl[n] = ALWAYS(pColl) ? pColl->zName : "BINARY"; n++; } } } - assert( (u32)n==pLoop->u.btree.nEq ); - - /* Add additional columns needed to make the automatic index into - ** a covering index */ - for(i=0; iaiColumn[n] = i; - pIdx->azColl[n] = "BINARY"; - n++; - } - } - if( pSrc->colUsed & MASKBIT(BMS-1) ){ - for(i=BMS-1; inCol; i++){ - pIdx->aiColumn[n] = i; - pIdx->azColl[n] = "BINARY"; - n++; - } - } - assert( n==nColumn ); - - /* Create the automatic index */ + assert( (u32)n==pLevel->plan.nEq ); + + /* Open the automatic index cursor */ pKeyinfo = sqlite4IndexKeyinfo(pParse, pIdx); assert( pLevel->iIdxCur>=0 ); - pLevel->iIdxCur = pParse->nTab++; - sqlite4VdbeAddOp4(v, OP_OpenAutoindex, pLevel->iIdxCur, nColumn+1, 0, - (char*)pKeyinfo, P4_KEYINFO_HANDOFF); + sqlite4VdbeAddOp3(v, OP_OpenAutoindex, pLevel->iIdxCur, 0, 0); + sqlite4VdbeChangeP4(v, -1, (char*)pKeyinfo, P4_KEYINFO_HANDOFF); VdbeComment((v, "for %s", pTable->zName)); - /* Fill the automatic index with content */ - iPkCsr = pLevel->iTabCur; - addrTop = sqlite4VdbeAddOp1(v, OP_Rewind, iPkCsr); + /* Populate the automatic index */ regRecord = sqlite4GetTempRange(pParse, 2); - regKey = regRecord + 1; - sqlite4EncodeIndexKey(pParse, 0, iPkCsr, pIdx, pLevel->iIdxCur, 1, regKey); - sqlite4EncodeIndexValue(pParse, iPkCsr, pIdx, regRecord); - sqlite4VdbeAddOp3(v, OP_Insert, pLevel->iIdxCur, regRecord, regKey); - /* sqlite4VdbeChangeP5(v, OPFLAG_USESEEKRESULT); */ - sqlite4VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); + regKey = regRecord+1; + addrRewind = sqlite4VdbeAddOp1(v, OP_Rewind, iPkCur); + sqlite4EncodeIndexKey(pParse, 0, iPkCur, pIdx, pLevel->iIdxCur, 1, regKey); + sqlite4VdbeAddOp2(v, OP_RowData, iPkCur, regRecord); + sqlite4VdbeAddOp3(v, OP_IdxInsert, pLevel->iIdxCur, regRecord, regKey); + sqlite4VdbeAddOp2(v, OP_Next, iPkCur, addrRewind+1); sqlite4VdbeChangeP5(v, SQLITE4_STMTSTATUS_AUTOINDEX); - sqlite4VdbeJumpHere(v, addrTop); + sqlite4VdbeJumpHere(v, addrRewind); sqlite4ReleaseTempRange(pParse, regRecord, 2); /* Jump here when skipping the initialization */ - sqlite4VdbeJumpHere(v, addrInit); + sqlite4VdbeJumpHere(v, addrOnce); } #endif /* SQLITE4_OMIT_AUTOMATIC_INDEX */ #ifndef SQLITE4_OMIT_VIRTUALTABLE /* @@ -2348,13 +2168,13 @@ ** Allocate and populate an sqlite4_index_info structure. It is the ** responsibility of the caller to eventually release the structure ** by passing the pointer returned by this function to sqlite4_free(). */ static sqlite4_index_info *allocateIndexInfo( - Parse *pParse, + Parse *pParse, WhereClause *pWC, - struct SrcListItem *pSrc, + SrcListItem *pSrc, ExprList *pOrderBy ){ int i, j; int nTerm; struct sqlite4_index_constraint *pIdxCons; @@ -2362,18 +2182,20 @@ struct sqlite4_index_constraint_usage *pUsage; WhereTerm *pTerm; int nOrderBy; sqlite4_index_info *pIdxInfo; + WHERETRACE(("Recomputing index info for %s...\n", pSrc->pTab->zName)); + /* Count the number of possible WHERE clause constraints referring ** to this virtual table */ for(i=nTerm=0, pTerm=pWC->a; inTerm; i++, pTerm++){ if( pTerm->leftCursor != pSrc->iCursor ) continue; - assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); - testcase( pTerm->eOperator & WO_IN ); - testcase( pTerm->eOperator & WO_ISNULL ); - if( pTerm->eOperator & (WO_ISNULL) ) continue; + assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); + testcase( pTerm->eOperator==WO_IN ); + testcase( pTerm->eOperator==WO_ISNULL ); + 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 @@ -2380,17 +2202,16 @@ ** virtual table then allocate space for the aOrderBy part of ** the sqlite4_index_info structure. */ nOrderBy = 0; if( pOrderBy ){ - int n = pOrderBy->nExpr; - for(i=0; inExpr; i++){ Expr *pExpr = pOrderBy->a[i].pExpr; if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break; } - if( i==n){ - nOrderBy = n; + if( i==pOrderBy->nExpr ){ + nOrderBy = pOrderBy->nExpr; } } /* Allocate the sqlite4_index_info structure */ @@ -2397,10 +2218,11 @@ pIdxInfo = sqlite4DbMallocZero(pParse->db, sizeof(*pIdxInfo) + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm + sizeof(*pIdxOrderBy)*nOrderBy ); if( pIdxInfo==0 ){ sqlite4ErrorMsg(pParse, "out of memory"); + /* (double)0 In case of SQLITE4_OMIT_FLOATING_POINT... */ return 0; } /* Initialize the structure. The sqlite4_index_info structure contains ** many fields that are declared "const" to prevent xBestIndex from @@ -2416,32 +2238,29 @@ *(struct sqlite4_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; *(struct sqlite4_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( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); - testcase( pTerm->eOperator & WO_IN ); - testcase( pTerm->eOperator & WO_ISNULL ); - if( pTerm->eOperator & (WO_ISNULL) ) continue; + assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); + testcase( pTerm->eOperator==WO_IN ); + testcase( pTerm->eOperator==WO_ISNULL ); + 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 & WO_ALL; - 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 SQLITE4_INDEX_CONSTRAINT_ codes are identical. The ** following asserts verify this fact. */ assert( WO_EQ==SQLITE4_INDEX_CONSTRAINT_EQ ); assert( WO_LT==SQLITE4_INDEX_CONSTRAINT_LT ); assert( WO_LE==SQLITE4_INDEX_CONSTRAINT_LE ); assert( WO_GT==SQLITE4_INDEX_CONSTRAINT_GT ); assert( WO_GE==SQLITE4_INDEX_CONSTRAINT_GE ); assert( WO_MATCH==SQLITE4_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; @@ -2452,12 +2271,12 @@ } /* ** The table object reference passed as the second argument to this function ** must represent a virtual table. This function invokes the xBestIndex() -** method of the virtual table with the sqlite4_index_info object that -** comes in as the 3rd argument to this function. +** method of the virtual table with the sqlite4_index_info pointer passed +** as the argument. ** ** If an error occurs, pParse is populated with an error message and a ** non-zero value is returned. Otherwise, 0 is returned and the output ** part of the sqlite4_index_info structure is left populated. ** @@ -2468,10 +2287,11 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite4_index_info *p){ sqlite4_vtab *pVtab = sqlite4GetVTable(pParse->db, pTab)->pVtab; int i; int rc; + WHERETRACE(("xBestIndex for %s\n", pTab->zName)); TRACE_IDX_INPUTS(p); rc = pVtab->pModule->xBestIndex(pVtab, p); TRACE_IDX_OUTPUTS(p); if( rc!=SQLITE4_OK ){ @@ -2493,13 +2313,167 @@ } } return pParse->nErr; } -#endif /* !defined(SQLITE4_OMIT_VIRTUALTABLE) */ +/* +** Compute the best index for a virtual table. +** +** The best index is computed by the xBestIndex method of the virtual +** table module. This routine is really just a wrapper that sets up +** the sqlite4_index_info structure that is used to communicate with +** xBestIndex. +** +** In a join, this routine might be called multiple times for the +** same virtual table. The sqlite4_index_info structure is created +** and initialized on the first invocation and reused on all subsequent +** invocations. The sqlite4_index_info structure is also used when +** code is generated to access the virtual table. The whereInfoDelete() +** routine takes care of freeing the sqlite4_index_info structure after +** everybody has finished with it. +*/ +static void bestVirtualIndex( + Parse *pParse, /* The parsing context */ + WhereClause *pWC, /* The WHERE clause */ + SrcListItem *pSrc, /* The FROM clause term to search */ + Bitmask notReady, /* Mask of cursors not available for index */ + Bitmask notValid, /* Cursors not valid for any purpose */ + ExprList *pOrderBy, /* The order by clause */ + WhereCost *pCost, /* Lowest cost query plan */ + sqlite4_index_info **ppIdxInfo /* Index information passed to xBestIndex */ +){ + Table *pTab = pSrc->pTab; + sqlite4_index_info *pIdxInfo; + struct sqlite4_index_constraint *pIdxCons; + struct sqlite4_index_constraint_usage *pUsage; + WhereTerm *pTerm; + int i, j; + int nOrderBy; + 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. + */ + memset(pCost, 0, sizeof(*pCost)); + pCost->plan.wsFlags = WHERE_VIRTUALTABLE; + + /* If the sqlite4_index_info structure has not been previously + ** allocated and initialized, then allocate and initialize it now. + */ + pIdxInfo = *ppIdxInfo; + if( pIdxInfo==0 ){ + *ppIdxInfo = pIdxInfo = allocateIndexInfo(pParse, pWC, pSrc, pOrderBy); + } + if( pIdxInfo==0 ){ + return; + } + + /* At this point, the sqlite4_index_info structure that pIdxInfo points + ** to will have been initialized, either during the current invocation or + ** during some prior invocation. Now we just have to customize the + ** details of pIdxInfo for the current invocation and pass it to + ** xBestIndex. + */ + + /* The module name must be defined. Also, by this point there must + ** be a pointer to an sqlite4_vtab structure. Otherwise + ** sqlite4ViewGetColumnNames() would have picked up the error. + */ + assert( pTab->azModuleArg && pTab->azModuleArg[0] ); + assert( sqlite4GetVTable(pParse->db, pTab) ); + + /* 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 sqlite4_index_constraint**)&pIdxInfo->aConstraint; + pUsage = pIdxInfo->aConstraintUsage; + for(i=0; inConstraint; i++, pIdxCons++){ + j = pIdxCons->iTermOffset; + pTerm = &pWC->a[j]; + pIdxCons->usable = (pTerm->prereqRight¬Ready) ? 0 : 1; + } + memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint); + if( pIdxInfo->needToFreeIdxStr ){ + sqlite4_free(pIdxInfo->idxStr); + } + pIdxInfo->idxStr = 0; + pIdxInfo->idxNum = 0; + pIdxInfo->needToFreeIdxStr = 0; + pIdxInfo->orderByConsumed = 0; + /* ((double)2) In case of SQLITE4_OMIT_FLOATING_POINT... */ + pIdxInfo->estimatedCost = SQLITE4_BIG_DBL / ((double)2); + nOrderBy = pIdxInfo->nOrderBy; + if( !pOrderBy ){ + pIdxInfo->nOrderBy = 0; + } + + if( vtabBestIndex(pParse, pTab, pIdxInfo) ){ + return; + } + + pIdxCons = *(struct sqlite4_index_constraint**)&pIdxInfo->aConstraint; + for(i=0; inConstraint; i++){ + if( pUsage[i].argvIndex>0 ){ + pCost->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 bestKVIndex(). + */ + rCost = pIdxInfo->estimatedCost; + if( pOrderBy && pIdxInfo->orderByConsumed==0 ){ + rCost += estLog(rCost)*rCost; + } + + /* The cost is not allowed to be larger than SQLITE4_BIG_DBL (the + ** inital value of lowestCost in this loop. If it is, then the + ** (costrCost = (SQLITE4_BIG_DBL/((double)2)); + }else{ + pCost->rCost = rCost; + } + pCost->plan.u.pVtabIdx = pIdxInfo; + if( pIdxInfo->orderByConsumed ){ + pCost->plan.wsFlags |= WHERE_ORDERBY; + } + pCost->plan.nEq = 0; + pIdxInfo->nOrderBy = nOrderBy; + + /* Try to find a more efficient access pattern by using multiple indexes + ** to optimize an OR expression within the WHERE clause. + */ + bestOrClauseIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost); +} +#endif /* SQLITE4_OMIT_VIRTUALTABLE */ + #ifdef SQLITE4_ENABLE_STAT3 /* ** Estimate the location of a particular key among all keys in an ** index. Store the results in aStat as follows: ** @@ -2628,26 +2602,23 @@ sqlite4ValueFree(pVal); return SQLITE4_OK; } #endif -/* -** TODO: Should this be ENABLE_STAT3 only. -** TODO: Comment this. -*/ static int whereSampleKeyinfo(Parse *pParse, Index *p, KeyInfo *pKeyInfo){ CollSeq *pColl; memset(pKeyInfo, 0, sizeof(KeyInfo)); + pKeyInfo->db = pParse->db; + pKeyInfo->enc = SQLITE4_UTF8; pKeyInfo->nField = p->nColumn; pKeyInfo->nPK = 1; pKeyInfo->nData = 0; pKeyInfo->aSortOrder = p->aSortOrder; pKeyInfo->aColl[0] = pColl = sqlite4LocateCollSeq(pParse, p->azColl[0]); pKeyInfo->aColl[0] = pColl; return pColl ? SQLITE4_OK : SQLITE4_ERROR; } - /* ** This function is used to estimate the number of rows that will be visited ** by scanning an index for a range of values. The range may have an upper ** bound, a lower bound, or both. The WHERE clause terms that set the upper @@ -2690,20 +2661,20 @@ Parse *pParse, /* Parsing & code generating context */ Index *p, /* The index containing the range-compared column; "x" */ int nEq, /* index into p->aCol[] of the range-compared column */ WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */ WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */ - WhereCost *pRangeDiv /* OUT: Reduce search space by this divisor */ + double *pRangeDiv /* OUT: Reduce search space by this divisor */ ){ int rc = SQLITE4_OK; #ifdef SQLITE4_ENABLE_STAT3 - if( nEq==0 && p->nSample && OptimizationEnabled(pParse->db, SQLITE4_Stat3) ){ + if( nEq==0 && p->nSample ){ sqlite4 *db = pParse->db; KeyInfo keyinfo; - sqlite4_buffer buf; + sqlite4_buffer buf; /* Buffer used for index sample */ tRowcnt iLower = 0; tRowcnt iUpper = p->aiRowEst[0]; tRowcnt a[2]; u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity; @@ -2711,57 +2682,51 @@ rc = whereSampleKeyinfo(pParse, p, &keyinfo); if( rc==SQLITE4_OK && pLower ){ Expr *pExpr = pLower->pExpr->pRight; rc = valueFromExpr(pParse, &keyinfo, pExpr, aff, &buf); - assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 ); + assert( pLower->eOperator==WO_GT || pLower->eOperator==WO_GE ); if( rc==SQLITE4_OK && buf.n && whereKeyStats(pParse, p, &buf, 0, a)==SQLITE4_OK ){ iLower = a[0]; - if( (pLower->eOperator & WO_GT)!=0 ) iLower += a[1]; + if( pLower->eOperator==WO_GT ) iLower += a[1]; } sqlite4_buffer_set(&buf, 0, 0); } if( rc==SQLITE4_OK && pUpper ){ Expr *pExpr = pUpper->pExpr->pRight; rc = valueFromExpr(pParse, &keyinfo, pExpr, aff, &buf); - assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 ); + assert( pUpper->eOperator==WO_LT || pUpper->eOperator==WO_LE ); if( rc==SQLITE4_OK && buf.n && whereKeyStats(pParse, p, &buf, 1, a)==SQLITE4_OK ){ iUpper = a[0]; - if( (pUpper->eOperator & WO_LE)!=0 ) iUpper += a[1]; + if( pUpper->eOperator==WO_LE ) iUpper += a[1]; } } sqlite4_buffer_clear(&buf); if( rc==SQLITE4_OK ){ - WhereCost iBase = whereCost(p->aiRowEst[0]); - if( iUpper>iLower ){ - iBase -= whereCost(iUpper - iLower); + if( iUpper<=iLower ){ + *pRangeDiv = (double)p->aiRowEst[0]; + }else{ + *pRangeDiv = (double)p->aiRowEst[0]/(double)(iUpper - iLower); } - *pRangeDiv = iBase; - WHERETRACE(0x100, ("range scan regions: %u..%u div=%d\n", - (u32)iLower, (u32)iUpper, *pRangeDiv)); + WHERETRACE(("range scan regions: %u..%u div=%g\n", + (u32)iLower, (u32)iUpper, *pRangeDiv)); return SQLITE4_OK; } } #else UNUSED_PARAMETER(pParse); UNUSED_PARAMETER(p); UNUSED_PARAMETER(nEq); #endif assert( pLower || pUpper ); - *pRangeDiv = 0; - /* TUNING: Each inequality constraint reduces the search space 4-fold. - ** A BETWEEN operator, therefore, reduces the search space 16-fold */ - if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){ - *pRangeDiv += 20; assert( 20==whereCost(4) ); - } - if( pUpper ){ - *pRangeDiv += 20; assert( 20==whereCost(4) ); - } + *pRangeDiv = (double)1; + if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ) *pRangeDiv *= (double)4; + if( pUpper ) *pRangeDiv *= (double)4; return rc; } #ifdef SQLITE4_ENABLE_STAT3 /* @@ -2783,40 +2748,40 @@ */ static int whereEqualScanEst( Parse *pParse, /* Parsing & code generating context */ Index *p, /* The index whose left-most column is pTerm */ Expr *pExpr, /* Expression for VALUE in the x=VALUE constraint */ - tRowcnt *pnRow /* Write the revised row estimate here */ + double *pnRow /* Write the revised row estimate here */ ){ - sqlite4_buffer buf; /* Encoded on right-hand side of pTerm */ + sqlite4_buffer buf; u8 aff; /* Column affinity */ int rc; /* Subfunction return code */ tRowcnt a[2]; /* Statistics */ assert( p->aSample!=0 ); assert( p->nSample>0 ); + sqlite4_buffer_init(&buf, pParse->db->pEnv->pMM); aff = p->pTable->aCol[p->aiColumn[0]].affinity; if( pExpr ){ KeyInfo keyinfo; rc = whereSampleKeyinfo(pParse, p, &keyinfo); if( rc==SQLITE4_OK ){ rc = valueFromExpr(pParse, &keyinfo, pExpr, aff, &buf); - if( rc==SQLITE4_OK && buf.n==0 ) rc = SQLITE4_NOTFOUND; + if( buf.n==0 ) return SQLITE4_NOTFOUND; } }else{ /* Populate the buffer with a NULL. */ u8 aNull[2] = {0x05, 0xfa}; /* ASC, DESC */ rc = sqlite4_buffer_set(&buf, &aNull[p->aSortOrder[0]], 1); } + if( rc ) goto whereEqualScanEst_cancel; + rc = whereKeyStats(pParse, p, &buf, 0, a); if( rc==SQLITE4_OK ){ - rc = whereKeyStats(pParse, p, &buf, 0, a); - if( rc==SQLITE4_OK ){ - WHERETRACE(0x100,("equality scan regions: %d\n", (int)a[1])); - *pnRow = a[1]; - } + WHERETRACE(("equality scan regions: %d\n", (int)a[1])); + *pnRow = a[1]; } whereEqualScanEst_cancel: sqlite4_buffer_clear(&buf); return rc; } @@ -2841,16 +2806,16 @@ */ static int whereInScanEst( Parse *pParse, /* Parsing & code generating context */ Index *p, /* The index whose left-most column is pTerm */ ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */ - tRowcnt *pnRow /* Write the revised row estimate here */ + double *pnRow /* Write the revised row estimate here */ ){ - int rc = SQLITE4_OK; /* Subfunction return code */ - tRowcnt nEst; /* Number of rows for a single term */ - tRowcnt nRowEst = 0; /* New estimate of the number of rows */ - int i; /* Loop counter */ + int rc = SQLITE4_OK; /* Subfunction return code */ + double nEst; /* Number of rows for a single term */ + double nRowEst = (double)0; /* New estimate of the number of rows */ + int i; /* Loop counter */ assert( p->aSample!=0 ); for(i=0; rc==SQLITE4_OK && inExpr; i++){ nEst = p->aiRowEst[0]; rc = whereEqualScanEst(pParse, p, pList->a[i].pExpr, &nEst); @@ -2857,15 +2822,580 @@ nRowEst += nEst; } if( rc==SQLITE4_OK ){ if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0]; *pnRow = nRowEst; - WHERETRACE(0x100,("IN row estimate: est=%g\n", nRowEst)); + WHERETRACE(("IN row estimate: est=%g\n", nRowEst)); } return rc; } #endif /* defined(SQLITE4_ENABLE_STAT3) */ + +/* +** Try to find a MATCH expression that constrains the pTabItem table in the +** WHERE clause. If one exists, set *piTerm to the index in the pWC->a[] array +** and return non-zero. If no such expression exists, return 0. +*/ +static int findMatchExpr( + Parse *pParse, + WhereClause *pWC, + SrcListItem *pTabItem, + int *piTerm +){ + int i; + int iCsr = pTabItem->iCursor; + + for(i=0; inTerm; i++){ + Expr *pMatch = pWC->a[i].pExpr; + if( pMatch->iTable==iCsr && pMatch->op==TK_MATCH ) break; + } + if( i==pWC->nTerm ) return 0; + + *piTerm = i; + return 1; +} + +static int bestMatchIdx( + Parse *pParse, + WhereClause *pWC, + SrcListItem *pTabItem, + Bitmask notReady, + WhereCost *pCost +){ + int iTerm; + + if( 0==findMatchExpr(pParse, pWC, pTabItem, &iTerm) ) return 0; + + /* Check that the MATCH expression is not composed using values from any + ** tables that are not ready. If it does, return 0. */ + if( notReady & pWC->a[iTerm].prereqAll ) return 0; + + pCost->used = pWC->a[iTerm].prereqAll; + pCost->rCost = 1.0; + pCost->plan.wsFlags = WHERE_INDEXED; + pCost->plan.nEq = 0; + pCost->plan.nRow = 10; + pCost->plan.u.pIdx = pWC->a[iTerm].pExpr->pIdx; + return 1; +} + +/* +** Find the best query plan for accessing a particular table. Write the +** best query plan and its cost into the WhereCost object supplied as the +** last parameter. +** +** The lowest cost plan wins. The cost is an estimate of the amount of +** CPU and disk I/O needed to process the requested result. +** Factors that influence cost include: +** +** * The estimated number of rows that will be retrieved. (The +** fewer the better.) +** +** * Whether or not sorting must occur. +** +** * Whether or not there must be separate lookups in the +** index and in the main table. +** +** If there was an INDEXED BY clause (pSrc->pIndex) attached to the table in +** the SQL statement, then this function only considers plans using the +** named index. If no such plan is found, then the returned cost is +** SQLITE4_BIG_DBL. If a plan is found that uses the named index, +** then the cost is calculated in the usual way. +** +** If a NOT INDEXED clause (pSrc->notIndexed!=0) was attached to the table +** in the SELECT statement, then no indexes are considered. However, the +** selected plan may still take advantage of the built-in rowid primary key +** index. +*/ +static void bestKVIndex( + Parse *pParse, /* The parsing context */ + WhereClause *pWC, /* The WHERE clause */ + SrcListItem *pSrc, /* The FROM clause term to search */ + Bitmask notReady, /* Mask of cursors not available for indexing */ + Bitmask notValid, /* Cursors not available for any purpose */ + ExprList *pOrderBy, /* The ORDER BY clause */ + ExprList *pDistinct, /* The select-list if query is DISTINCT */ + WhereCost *pCost /* Lowest cost query plan */ +){ + int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */ + Index *pProbe; /* An index we are evaluating */ + Index *pFirst; /* First index to evaluate */ + Index *pPk; /* Primary Key index */ + int eqTermMask; /* Current mask of valid equality operators */ + int idxEqTermMask; /* Index mask of valid equality operators */ + + /* Initialize the cost to a worst-case value */ + memset(pCost, 0, sizeof(*pCost)); + pCost->rCost = SQLITE4_BIG_DBL; + pPk = sqlite4FindPrimaryKey(pSrc->pTab, 0); + + /* If the pSrc table is the right table of a LEFT JOIN then we may not + ** use an index to satisfy IS NULL constraints on that table. This is + ** because columns might end up being NULL if the table does not match - + ** a circumstance which the index cannot help us discover. Ticket #2177. + */ + if( pSrc->jointype & JT_LEFT ){ + idxEqTermMask = WO_EQ|WO_IN; + }else{ + idxEqTermMask = WO_EQ|WO_IN|WO_ISNULL; + } + + /* Normally, this function considers all indexes attached to the table + ** being queried. Except, if an INDEXED BY clause is specified then only + ** the named index is considered. And if a NOT INDEXED clause was present + ** only the PRIMARY KEY index may be considered. + */ + if( pSrc->notIndexed ){ + pFirst = pPk; + }else if( pSrc->pIndex ){ + pFirst = pSrc->pIndex; + }else{ + pFirst = pSrc->pTab->pIndex; + } + eqTermMask = idxEqTermMask; + + /* Loop over all indices looking for the best one to use */ + for(pProbe=pFirst; pProbe; pProbe=pProbe->pNext){ + const tRowcnt * const aiRowEst = pProbe->aiRowEst; + double cost; /* Cost of using pProbe */ + double nRow; /* Estimated number of rows in result set */ + double log10N = (double)1; /* base-10 logarithm of nRow (inexact) */ + int rev; /* True to scan in reverse order */ + int wsFlags = 0; + Bitmask used = 0; + + /* The following variables are populated based on the properties of + ** index being evaluated. They are then used to determine the expected + ** cost and number of rows returned. + ** + ** nEq: + ** Number of equality terms that can be implemented using the index. + ** In other words, the number of initial fields in the index that + ** are used in == or IN or NOT NULL constraints of the WHERE clause. + ** + ** nInMul: + ** The "in-multiplier". This is an estimate of how many seek operations + ** SQLite must perform on the index in question. For example, if the + ** WHERE clause is: + ** + ** WHERE a IN (1, 2, 3) AND b IN (4, 5, 6) + ** + ** SQLite must perform 9 lookups on an index on (a, b), so nInMul is + ** set to 9. Given the same schema and either of the following WHERE + ** clauses: + ** + ** WHERE a = 1 + ** WHERE a >= 2 + ** + ** nInMul is set to 1. + ** + ** If there exists a WHERE term of the form "x IN (SELECT ...)", then + ** the sub-select is assumed to return 25 rows for the purposes of + ** determining nInMul. + ** + ** bInEst: + ** Set to true if there was at least one "x IN (SELECT ...)" term used + ** in determining the value of nInMul. Note that the RHS of the + ** IN operator must be a SELECT, not a value list, for this variable + ** to be true. + ** + ** rangeDiv: + ** An estimate of a divisor by which to reduce the search space due + ** to inequality constraints. In the absence of sqlite_stat3 ANALYZE + ** data, a single inequality reduces the search space to 1/4rd its + ** original size (rangeDiv==4). Two inequalities reduce the search + ** space to 1/16th of its original size (rangeDiv==16). + ** + ** bSort: + ** Boolean. True if there is an ORDER BY clause that will require an + ** external sort (i.e. scanning the index being evaluated will not + ** correctly order records). + ** + ** bLookup: + ** Boolean. True if a table lookup is required for each index entry + ** visited. In other words, true if this is not a covering index. + ** This is always false for the rowid primary key index of a table. + ** For other indexes, it is true unless all the columns of the table + ** used by the SELECT statement are present in the index (such an + ** index is sometimes described as a covering index). + ** For example, given the index on (a, b), the second of the following + ** two queries requires table b-tree lookups in order to find the value + ** of column c, but the first does not because columns a and b are + ** both available in the index. + ** + ** SELECT a, b FROM tbl WHERE a = 1; + ** SELECT a, b, c FROM tbl WHERE a = 1; + */ + int nEq; /* Number of == or IN terms matching index */ + int bInEst = 0; /* True if "x IN (SELECT...)" seen */ + int nInMul = 1; /* Number of distinct equalities to lookup */ + double rangeDiv = (double)1; /* Estimated reduction in search space */ + int nBound = 0; /* Number of range constraints seen */ + int bSort = !!pOrderBy; /* True if external sort required */ + int bDist = !!pDistinct; /* True if index cannot help with DISTINCT */ + int bLookup = 0; /* True if not the PK index */ + WhereTerm *pTerm; /* A single term of the WHERE clause */ +#ifdef SQLITE4_ENABLE_STAT3 + WhereTerm *pFirstTerm = 0; /* First term matching the index */ +#endif + int nCol = pProbe->nColumn; /* Total columns in index record */ + + if( pProbe->eIndexType==SQLITE4_INDEX_FTS5 ) continue; + + /* Unless pProbe is the primary key index, then the encoded PK column + ** values are at the end of each record. Set variable nCol to the total + ** number of columns encoded into each index record, including the PK + ** columns. */ + if( pProbe!=pPk ) nCol += pPk->nColumn; + + /* Determine the values of nEq and nInMul */ + for(nEq=0; nEqpWC!=pWC ); + if( pTerm->eOperator & WO_IN ){ + Expr *pExpr = pTerm->pExpr; + wsFlags |= WHERE_COLUMN_IN; + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + /* "x IN (SELECT ...)": Assume the SELECT returns 25 rows */ + nInMul *= 25; + bInEst = 1; + }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ + /* "x IN (value, value, ...)" */ + nInMul *= pExpr->x.pList->nExpr; + } + }else if( pTerm->eOperator & WO_ISNULL ){ + wsFlags |= WHERE_COLUMN_NULL; + } +#ifdef SQLITE4_ENABLE_STAT3 + if( nEq==0 && pProbe->aSample ) pFirstTerm = pTerm; +#endif + used |= pTerm->prereqRight; + } + + /* If the index being considered is UNIQUE, and there is an equality + ** constraint for all columns in the index, then this search will find + ** at most a single row. In this case set the WHERE_UNIQUE flag to + ** indicate this to the caller. + ** + ** Otherwise, if the search may find more than one row, test to see if + ** there is a range constraint on indexed column (nEq+1) that can be + ** optimized using the index. + */ + if( nEq>=pProbe->nColumn && pProbe->onError!=OE_None ){ + testcase( wsFlags & WHERE_COLUMN_IN ); + testcase( wsFlags & WHERE_COLUMN_NULL ); + if( (wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){ + wsFlags |= WHERE_UNIQUE; + } + }else if( (pProbe->fIndex & IDX_Unordered)==0 ){ + int j = idxColumnNumber(pProbe, pPk, nEq); + if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pProbe) ){ + WhereTerm *pTop = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pProbe); + WhereTerm *pBtm = findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pProbe); + whereRangeScanEst(pParse, pProbe, nEq, pBtm, pTop, &rangeDiv); + if( pTop ){ + nBound = 1; + wsFlags |= WHERE_TOP_LIMIT; + used |= pTop->prereqRight; + testcase( pTop->pWC!=pWC ); + } + if( pBtm ){ + nBound++; + wsFlags |= WHERE_BTM_LIMIT; + used |= pBtm->prereqRight; + testcase( pBtm->pWC!=pWC ); + } + wsFlags |= WHERE_COLUMN_RANGE; + } + } + + /* If there is an ORDER BY clause and the index being considered will + ** naturally scan rows in the required order, set the appropriate flags + ** in wsFlags. Otherwise, if there is an ORDER BY clause but the index + ** will scan rows in a different order, set the bSort variable. */ + if( isSortingIndex( + pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy, nEq, wsFlags, &rev) + ){ + bSort = 0; + wsFlags |= WHERE_COLUMN_RANGE|WHERE_ORDERBY; + wsFlags |= (rev ? WHERE_REVERSE : 0); + } + + /* If there is a DISTINCT qualifier and this index will scan rows in + ** order of the DISTINCT expressions, clear bDist and set the appropriate + ** flags in wsFlags. */ + if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq) ){ + bDist = 0; + wsFlags |= WHERE_COLUMN_RANGE|WHERE_DISTINCT; + } + + /* If currently calculating the cost of using an index (not the PK + ** index), determine if all required column data may be obtained without + ** using the main table (i.e. if the index is a covering + ** index for this query). If it is, set the WHERE_IDX_ONLY flag in + ** wsFlags. Otherwise, set the bLookup variable to true. + ** + ** TODO: Not clear if this optimization can be applied in SQLite 4. Fix + ** this block once that is figured out. + */ +#if 0 + if( wsFlags ){ + Bitmask m = pSrc->colUsed; + int j; + for(j=0; jnColumn; j++){ + int x = pProbe->aiColumn[j]; + if( xeIndexType!=SQLITE4_INDEX_PRIMARYKEY); + + /* + ** Estimate the number of rows of output. For an "x IN (SELECT...)" + ** constraint, do not let the estimate exceed half the rows in the table. + */ + nRow = (double)(aiRowEst[nEq] * nInMul); + if( bInEst && nRow*2>aiRowEst[0] ){ + nRow = aiRowEst[0]/2; + nInMul = (int)(nRow / aiRowEst[nEq]); + } + +#ifdef SQLITE4_ENABLE_STAT3 + /* If the constraint is of the form x=VALUE or x IN (E1,E2,...) + ** and we do not think that values of x are unique and if histogram + ** data is available for column x, then it might be possible + ** to get a better estimate on the number of rows based on + ** VALUE and how common that value is according to the histogram. + */ + if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 && aiRowEst[1]>1 ){ + assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 ); + if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){ + testcase( pFirstTerm->eOperator==WO_EQ ); + testcase( pFirstTerm->eOperator==WO_ISNULL ); + whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow); + }else if( bInEst==0 ){ + assert( pFirstTerm->eOperator==WO_IN ); + whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList, &nRow); + } + } +#endif /* SQLITE4_ENABLE_STAT3 */ + + /* Adjust the number of output rows and downward to reflect rows + ** that are excluded by range constraints. + */ + nRow = nRow/rangeDiv; + if( nRow<1 ) nRow = 1; + + /* Experiments run on real SQLite databases show that the time needed + ** to do a binary search to locate a row in a table or index is roughly + ** log10(N) times the time to move from one row to the next row within + ** a table or index. The actual times can vary, with the size of + ** records being an important factor. Both moves and searches are + ** slower with larger records, presumably because fewer records fit + ** on one page and hence more pages have to be fetched. + ** + ** The ANALYZE command and the sqlite_stat1 and sqlite_stat3 tables do + ** not give us data on the relative sizes of table and index records. + ** So this computation assumes table records are about twice as big + ** as index records + */ + if( (wsFlags & WHERE_NOT_FULLSCAN)==0 ){ + /* The cost of a full table scan is a number of move operations equal + ** to the number of rows in the table. + ** + ** We add an additional 4x penalty to full table scans. This causes + ** the cost function to err on the side of choosing an index over + ** choosing a full scan. This 4x full-scan penalty is an arguable + ** decision and one which we expect to revisit in the future. But + ** it seems to be working well enough at the moment. + */ + cost = aiRowEst[0]*4; + }else{ + log10N = estLog(aiRowEst[0]); + cost = nRow; + if( bLookup ){ + /* For an index lookup followed by a table lookup: + ** nInMul index searches to find the start of each index range + ** + nRow steps through the index + ** + nRow table searches to lookup the table entry using the PK + */ + cost += (nInMul + nRow)*log10N; + }else{ + /* For a covering index: + ** nInMul index searches to find the initial entry + ** + nRow steps through the index + */ + cost += nInMul*log10N; + } + } + + /* Add in the estimated cost of sorting the result. Actual experimental + ** measurements of sorting performance in SQLite show that sorting time + ** adds C*N*log10(N) to the cost, where N is the number of rows to be + ** sorted and C is a factor between 1.95 and 4.3. We will split the + ** difference and select C of 3.0. + */ + if( bSort ){ + cost += nRow*estLog(nRow)*3; + } + if( bDist ){ + cost += nRow*estLog(nRow)*3; + } + + /**** Cost of using this index has now been computed ****/ + + /* If there are additional constraints on this table that cannot + ** be used with the current index, but which might lower the number + ** of output rows, adjust the nRow value accordingly. This only + ** matters if the current index is the least costly, so do not bother + ** with this step if we already know this index will not be chosen. + ** Also, never reduce the output row count below 2 using this step. + ** + ** It is critical that the notValid mask be used here instead of + ** the notReady mask. When computing an "optimal" index, the notReady + ** mask will only have one bit set - the bit for the current table. + ** The notValid mask, on the other hand, always has all bits set for + ** tables that are not in outer loops. If notReady is used here instead + ** of notValid, then a optimal index that depends on inner joins loops + ** might be selected even when there exists an optimal index that has + ** no such dependency. + */ + if( nRow>2 && cost<=pCost->rCost ){ + int k; /* Loop counter */ + int nSkipEq = nEq; /* Number of == constraints to skip */ + int nSkipRange = nBound; /* Number of < constraints to skip */ + Bitmask thisTab; /* Bitmap for pSrc */ + + thisTab = getMask(pWC->pMaskSet, iCur); + for(pTerm=pWC->a, k=pWC->nTerm; nRow>2 && k; k--, pTerm++){ + if( pTerm->wtFlags & TERM_VIRTUAL ) continue; + if( (pTerm->prereqAll & notValid)!=thisTab ) continue; + if( pTerm->eOperator & (WO_EQ|WO_IN|WO_ISNULL) ){ + if( nSkipEq ){ + /* Ignore the first nEq equality matches since the index + ** has already accounted for these */ + nSkipEq--; + }else{ + /* Assume each additional equality match reduces the result + ** set size by a factor of 10 */ + nRow /= 10; + } + }else if( pTerm->eOperator & (WO_LT|WO_LE|WO_GT|WO_GE) ){ + if( nSkipRange ){ + /* Ignore the first nSkipRange range constraints since the index + ** has already accounted for these */ + nSkipRange--; + }else{ + /* Assume each additional range constraint reduces the result + ** set size by a factor of 3. Indexed range constraints reduce + ** the search space by a larger factor: 4. We make indexed range + ** more selective intentionally because of the subjective + ** observation that indexed range constraints really are more + ** selective in practice, on average. */ + nRow /= 3; + } + }else if( pTerm->eOperator!=WO_NOOP ){ + /* Any other expression lowers the output row count by half */ + nRow /= 2; + } + } + if( nRow<2 ) nRow = 2; + } + + + WHERETRACE(( + "%s(%s): nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%x\n" + " notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f used=0x%llx\n", + pSrc->pTab->zName, pProbe->zName, + nEq, nInMul, (int)rangeDiv, bSort, bLookup, wsFlags, + notReady, log10N, nRow, cost, used + )); + + /* If this index is the best we have seen so far, then record this + ** index and its cost in the pCost structure. + */ + if( (pProbe==pFirst || wsFlags) + && (costrCost || (cost<=pCost->rCost && nRowplan.nRow)) + ){ + pCost->rCost = cost; + pCost->used = used; + pCost->plan.nRow = nRow; + pCost->plan.wsFlags = wsFlags; + pCost->plan.nEq = nEq; + pCost->plan.u.pIdx = pProbe; + } + + /* If there was an INDEXED BY or NOT INDEXED clause, only one index is + ** considered. */ + if( pSrc->pIndex || pSrc->notIndexed ) break; + } + + /* If there is no ORDER BY clause and the SQLITE4_ReverseOrder flag + ** is set, then reverse the order that the index will be scanned + ** in. This is used for application testing, to help find cases + ** where application behaviour depends on the (undefined) order that + ** SQLite outputs rows in in the absence of an ORDER BY clause. */ + if( !pOrderBy && pParse->db->flags & SQLITE4_ReverseOrder ){ + pCost->plan.wsFlags |= WHERE_REVERSE; + } + + assert( pOrderBy || (pCost->plan.wsFlags&WHERE_ORDERBY)==0 ); + assert( pSrc->pIndex==0 + || pCost->plan.u.pIdx==0 + || pCost->plan.u.pIdx==pSrc->pIndex + ); + + WHERETRACE(("best index is: %s\n", + ((pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ? "none" : + pCost->plan.u.pIdx ? pCost->plan.u.pIdx->zName : "ipk") + )); + + bestOrClauseIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost); + bestAutomaticIndex(pParse, pWC, pSrc, notReady, pCost); + pCost->plan.wsFlags |= eqTermMask; +} + +/* +** Find the query plan for accessing table pSrc->pTab. Write the +** best query plan and its cost into the WhereCost object supplied +** as the last parameter. This function may calculate the cost of +** both real and virtual table scans. +*/ +static void bestIndex( + Parse *pParse, /* The parsing context */ + WhereClause *pWC, /* The WHERE clause */ + SrcListItem *pSrc, /* The FROM clause term to search */ + Bitmask notReady, /* Mask of cursors not available for indexing */ + Bitmask notValid, /* Cursors not available for any purpose */ + ExprList *pOrderBy, /* The ORDER BY clause */ + WhereCost *pCost /* Lowest cost query plan */ +){ +#ifndef SQLITE4_OMIT_VIRTUALTABLE + if( IsVirtual(pSrc->pTab) ){ + sqlite4_index_info *p = 0; + bestVirtualIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost,&p); + if( p->needToFreeIdxStr ){ + sqlite4_free(p->idxStr); + } + sqlite4DbFree(pParse->db, p); + }else +#endif + { + bestKVIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, 0, pCost); + } +} /* ** Disable a term in the WHERE clause. Except, do not disable the term ** if it controls a LEFT OUTER JOIN and it did not originate in the ON ** or USING clause of that join. @@ -2958,13 +3488,11 @@ ** this routine sets up a loop that will iterate over all values of X. */ static int codeEqualityTerm( Parse *pParse, /* The parsing context */ WhereTerm *pTerm, /* The term of the WHERE clause to be coded */ - WhereLevel *pLevel, /* The level of the FROM clause we are working on */ - int iEq, /* Index of the equality term within this level */ - int bRev, /* True for reverse-order IN operations */ + WhereLevel *pLevel, /* When level of the FROM clause we are working on */ int iTarget /* Attempt to leave results in this register */ ){ Expr *pX = pTerm->pExpr; Vdbe *v = pParse->pVdbe; int iReg; /* Register holding results */ @@ -2975,54 +3503,72 @@ }else if( pX->op==TK_ISNULL ){ iReg = iTarget; sqlite4VdbeAddOp2(v, OP_Null, 0, iReg); #ifndef SQLITE4_OMIT_SUBQUERY }else{ - int eType; + /* Code a loop that iterates through the set of distinct, non-null + ** values in the set on the right-hand-side of the IN(...) operator. + ** There are two ways to do this: + ** + ** * If the SELECT statement is of the form "SELECT x FROM tbl", + ** and column x is subject to a UNIQUE constraint, and the + ** default affinity and collation sequence of column "x" match + ** those required by the comparison, iterate through the PK + ** index. + ** + ** * Otherwise, materialize the set into an ephemeral index using + ** "x" as both the key and value. Then loop through the contents + ** of the ephemeral index. + */ + sqlite4 *db = pParse->db; int iTab; - int iCov; + int iCol; /* Column to read from cursor iTab */ struct InLoop *pIn; - WhereLoop *pLoop = pLevel->pWLoop; - - if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 - && pLoop->u.btree.pIndex!=0 - && pLoop->u.btree.pIndex->aSortOrder[iEq] - ){ - testcase( iEq==0 ); - testcase( bRev ); - bRev = !bRev; - } + assert( pX->op==TK_IN ); iReg = iTarget; - eType = sqlite4FindInIndex(pParse, pX, 0, &iCov); - if( eType==IN_INDEX_INDEX_DESC ){ - testcase( bRev ); - bRev = !bRev; - } - iTab = pX->iTable; - sqlite4VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0); - assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 ); - pLoop->wsFlags |= WHERE_IN_ABLE; - if( pLevel->u.in.nIn==0 ){ - pLevel->addrNxt = sqlite4VdbeMakeLabel(v); - } + + if( sqlite4FindExistingInIndex(pParse, pX, 1) ){ + /* This branch is taken if the rhs of the IN is a select of the + ** form "SELECT x FROM tble" and column x is subject to a UNIQUE + ** constraint that uses the same collation sequence and affinity as + ** this IN (...) test. In this case just loop through all values of + ** "x", skipping any NULLs. */ + Table *pTab = pX->x.pSelect->pSrc->a[0].pTab; + int iDb = sqlite4SchemaToIndex(db, pTab->pSchema); + iTab = pX->iTable = pParse->nTab++; + sqlite4OpenPrimaryKey(pParse, iTab, iDb, pTab, OP_OpenRead); + iCol = pX->pLeft->iColumn; + }else{ + /* Set Parse.nQueryLoop to 1 before calling sqlite4CodeSubselect(). + ** This informs the optimizer that there is no point in constructing + ** any automatic indexes for the outer loop of the sub-select, as it + ** will only be run once. See also bestAutomaticIndex(). */ + int nQueryLoopSave = pParse->nQueryLoop; + pParse->nQueryLoop = (double)1; + sqlite4CodeSubselect(pParse, pX, 0, 0); + pParse->nQueryLoop = nQueryLoopSave; + iTab = pX->iTable; + iCol = 0; + } + sqlite4VdbeAddOp2(v, OP_Rewind, iTab, 0); + assert( pLevel->plan.wsFlags & WHERE_IN_ABLE ); + + if( pLevel->u.in.nIn==0 ) pLevel->addrNxt = sqlite4VdbeMakeLabel(v); pLevel->u.in.nIn++; - pLevel->u.in.aInLoop = - sqlite4DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop, - sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn); + pLevel->u.in.aInLoop = sqlite4DbReallocOrFree(db, pLevel->u.in.aInLoop, + (sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn) + ); pIn = pLevel->u.in.aInLoop; + if( pIn ){ pIn += pLevel->u.in.nIn - 1; pIn->iCur = iTab; - if( eType==IN_INDEX_ROWID ){ - pIn->addrInTop = sqlite4VdbeAddOp2(v, OP_Rowid, iTab, iReg); - }else{ - pIn->addrInTop = sqlite4VdbeAddOp3(v, OP_Column, iTab, iCov, iReg); - } - pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next; + pIn->addrInTop = sqlite4VdbeAddOp3(v, OP_Column, iTab, iCol, iReg); sqlite4VdbeAddOp1(v, OP_IsNull, iReg); }else{ + assert( db->mallocFailed ); pLevel->u.in.nIn = 0; } #endif } disableTerm(pLevel, pTerm); @@ -3069,54 +3615,53 @@ ** string in this example would be set to SQLITE4_AFF_NONE. */ static int codeAllEqualityTerms( Parse *pParse, /* Parsing context */ WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */ - int bRev, /* Reverse the order of IN operators */ + WhereClause *pWC, /* The WHERE clause */ + Bitmask notReady, /* Which parts of FROM have not yet been coded */ int nExtraReg, /* Number of extra registers to allocate */ char **pzAff /* OUT: Set to point to affinity string */ ){ - int nEq; /* The number of == or IN constraints to code */ + int nEq = pLevel->plan.nEq; /* The number of == or IN constraints to code */ Vdbe *v = pParse->pVdbe; /* The vm under construction */ Index *pIdx; /* The index being used for this loop */ + int iCur = pLevel->iTabCur; /* The cursor of the table */ WhereTerm *pTerm; /* A single constraint term */ - WhereLoop *pLoop; /* The WhereLoop object */ int j; /* Loop counter */ int regBase; /* Base register */ int nReg; /* Number of registers to allocate */ char *zAff; /* Affinity string to return */ /* This module is only called on query plans that use an index. */ - pLoop = pLevel->pWLoop; - assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ); - nEq = pLoop->u.btree.nEq; - pIdx = pLoop->u.btree.pIndex; - assert( pIdx!=0 ); + assert( pLevel->plan.wsFlags & WHERE_INDEXED ); + pIdx = pLevel->plan.u.pIdx; /* Figure out how many memory cells we will need then allocate them. */ regBase = pParse->nMem + 1; - nReg = pLoop->u.btree.nEq + nExtraReg; + nReg = pLevel->plan.nEq + nExtraReg; pParse->nMem += nReg; zAff = sqlite4DbStrDup(pParse->db, sqlite4IndexAffinityStr(v, pIdx)); if( !zAff ){ pParse->db->mallocFailed = 1; } /* Evaluate the equality constraints */ - assert( idxColumnCount(pIdx, sqlite4FindPrimaryKey(pIdx->pTable, 0))>=nEq ); + assert( pIdx->nColumn>=nEq ); for(j=0; jaLTerm[j]; - assert( pTerm!=0 ); + int k = pIdx->aiColumn[j]; + pTerm = findTerm(pWC, iCur, k, notReady, pLevel->plan.wsFlags, pIdx); + if( NEVER(pTerm==0) ) break; /* The following true for indices with redundant columns. ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */ testcase( (pTerm->wtFlags & TERM_CODED)!=0 ); testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ - r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, regBase+j); + r1 = codeEqualityTerm(pParse, pTerm, pLevel, regBase+j); if( r1!=regBase+j ){ if( nReg==1 ){ sqlite4ReleaseTempReg(pParse, regBase); regBase = r1; }else{ @@ -3180,36 +3725,38 @@ ** ** The returned pointer points to memory obtained from sqlite4DbMalloc(). ** It is the responsibility of the caller to free the buffer when it is ** no longer required. */ -static char *explainIndexRange(sqlite4 *db, WhereLoop *pLoop, Table *pTab){ - Index *pIndex = pLoop->u.btree.pIndex; - int nEq = pLoop->u.btree.nEq; - int i, j; - Column *aCol = pTab->aCol; - int *aiColumn = pIndex->aiColumn; +static char *explainIndexRange(sqlite4 *db, WhereLevel *pLevel, Table *pTab){ + WherePlan *pPlan = &pLevel->plan; + Index *pPk; + Index *pIdx = pPlan->u.pIdx; + int nEq = pPlan->nEq; + int i; StrAccum txt; - if( nEq==0 && (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){ + pPk = sqlite4FindPrimaryKey(pTab, 0); + if( nEq==0 && (pPlan->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){ return 0; } sqlite4StrAccumInit(&txt, 0, 0, SQLITE4_MAX_LENGTH); txt.db = db; + txt.pEnv = db->pEnv; + sqlite4StrAccumAppend(&txt, " (", 2); for(i=0; i"); - } - if( pLoop->wsFlags&WHERE_TOP_LIMIT ){ - char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName; - explainAppendTerm(&txt, i, z, "<"); + const char *zCol = tblColumnName(pTab, idxColumnNumber(pIdx, pPk, i)); + explainAppendTerm(&txt, i, zCol, "="); + } + if( pPlan->wsFlags&WHERE_BTM_LIMIT ){ + const char *zCol = tblColumnName(pTab, idxColumnNumber(pIdx, pPk, nEq)); + explainAppendTerm(&txt, i++, zCol, ">"); + } + if( pPlan->wsFlags&WHERE_TOP_LIMIT ){ + const char *zCol = tblColumnName(pTab, idxColumnNumber(pIdx, pPk, nEq)); + explainAppendTerm(&txt, i, zCol, "<"); } sqlite4StrAccumAppend(&txt, ")", 1); return sqlite4StrAccumFinish(&txt); } @@ -3226,26 +3773,24 @@ int iLevel, /* Value for "level" column of output */ int iFrom, /* Value for "from" column of output */ u16 wctrlFlags /* Flags passed to sqlite4WhereBegin() */ ){ if( pParse->explain==2 ){ - struct SrcListItem *pItem = &pTabList->a[pLevel->iFrom]; + u32 flags = pLevel->plan.wsFlags; + SrcListItem *pItem = &pTabList->a[pLevel->iFrom]; Vdbe *v = pParse->pVdbe; /* VM being constructed */ sqlite4 *db = pParse->db; /* Database handle */ char *zMsg; /* Text to add to EQP output */ + sqlite4_int64 nRow; /* Expected number of rows visited by scan */ int iId = pParse->iSelectId; /* Select id (left-most output column) */ int isSearch; /* True for a SEARCH. False for SCAN. */ - WhereLoop *pLoop; /* The controlling WhereLoop object */ - u32 flags; /* Flags that describe this loop */ - pLoop = pLevel->pWLoop; - flags = pLoop->wsFlags; if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return; - isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 - || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0)) - || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); + isSearch = (pLevel->plan.nEq>0) + || (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 + || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); zMsg = sqlite4MPrintf(db, "%s", isSearch?"SEARCH":"SCAN"); if( pItem->pSelect ){ zMsg = sqlite4MAppendf(db, zMsg, "%s SUBQUERY %d", zMsg,pItem->iSelectId); }else{ @@ -3253,110 +3798,80 @@ } if( pItem->zAlias ){ zMsg = sqlite4MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias); } - if( (flags & WHERE_VIRTUALTABLE)==0 - && ALWAYS(pLoop->u.btree.pIndex!=0) - ){ - char *zWhere = explainIndexRange(db, pLoop, pItem->pTab); - Index *pIdx = pLoop->u.btree.pIndex; - if( flags & WHERE_AUTO_INDEX ){ - zMsg = sqlite4MAppendf(db, zMsg, "%s USING AUTOMATIC COVERING INDEX%s", - zMsg, zWhere - ); - }else if( pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY ){ - if( isSearch ){ - zMsg = sqlite4MAppendf(db, zMsg, "%s USING PRIMARY KEY%s", - zMsg, zWhere - ); - } - }else{ - const char *zCover = (flags & WHERE_IDX_ONLY) ? " COVERING" : ""; - zMsg = sqlite4MAppendf(db, zMsg, "%s USING%s INDEX %s%s", - zMsg, zCover, pIdx->zName, zWhere - ); - } + if( (flags & WHERE_INDEXED)!=0 ){ + char *zWhere = explainIndexRange(db, pLevel, pItem->pTab); + Index *pIdx = pLevel->plan.u.pIdx; + const char *zName = ""; + const char *zType = "INDEX"; + + if( pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY ){ + zType = "PRIMARY KEY"; + }else if( 0==(flags & WHERE_TEMP_INDEX) ){ + zName = pIdx->zName; + } + zMsg = sqlite4MAppendf(db, zMsg, "%s USING %s%s%s%s%s", zMsg, + ((flags & WHERE_TEMP_INDEX)?"AUTOMATIC ":""), + zType, (zName[0] ? " " : ""), zName, zWhere + ); sqlite4DbFree(db, zWhere); } #ifndef SQLITE4_OMIT_VIRTUALTABLE else if( (flags & WHERE_VIRTUALTABLE)!=0 ){ + sqlite4_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx; zMsg = sqlite4MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg, - pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr); + pVtabIdx->idxNum, pVtabIdx->idxStr); } #endif - zMsg = sqlite4MAppendf(db, zMsg, "%s", zMsg); + if( wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX) ){ + testcase( wctrlFlags & WHERE_ORDERBY_MIN ); + nRow = 1; + }else{ + nRow = (sqlite4_int64)pLevel->plan.nRow; + } + zMsg = sqlite4MAppendf(db, zMsg, "%s (~%lld rows)", zMsg, nRow); sqlite4VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg, P4_DYNAMIC); } } #else # define explainOneScan(u,v,w,x,y,z) #endif /* SQLITE4_OMIT_EXPLAIN */ - - -/* -** Try to find a MATCH expression that constrains the pTabItem table in the -** WHERE clause. If one exists, set *piTerm to the index in the pWC->a[] array -** and return non-zero. If no such expression exists, return 0. -*/ -static int findMatchExpr( - WhereClause *pWC, - SrcListItem *pTabItem, - int *piTerm -){ - int i; - int iCsr = pTabItem->iCursor; - - for(i=0; inTerm; i++){ - Expr *pMatch = pWC->a[i].pExpr; - if( pMatch->iTable==iCsr && pMatch->op==TK_MATCH ) break; - } - if( i==pWC->nTerm ) return 0; - - *piTerm = i; - return 1; -} - /* ** Generate code for the start of the iLevel-th loop in the WHERE clause ** implementation described by pWInfo. */ static Bitmask codeOneLoopStart( WhereInfo *pWInfo, /* Complete information about the WHERE clause */ int iLevel, /* Which level of pWInfo->a[] should be coded */ - Bitmask notReady /* Which tables are currently available */ + u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */ + Bitmask notReady, /* Which tables are currently available */ + Expr *pWhere /* Complete WHERE clause */ ){ int j, k; /* Loop counters */ int iCur; /* The VDBE cursor for the table */ int addrNxt; /* Where to jump to continue with the next IN case */ - int omitTable; /* True if we use the index only */ int bRev; /* True if we need to scan in reverse order */ WhereLevel *pLevel; /* The where level to be coded */ - WhereLoop *pLoop; /* The WhereLoop object being coded */ WhereClause *pWC; /* Decomposition of the entire WHERE clause */ WhereTerm *pTerm; /* A WHERE clause term */ Parse *pParse; /* Parsing context */ Vdbe *v; /* The prepared stmt under constructions */ - struct SrcListItem *pTabItem; /* FROM clause term being coded */ + SrcListItem *pTabItem; /* FROM clause term being coded */ int addrBrk; /* Jump here to break out of the loop */ int addrCont; /* Jump here to continue with next cycle */ - int iRowidReg = 0; /* Rowid is stored in this register, if not zero */ - int iReleaseReg = 0; /* Temp register to free before returning */ - Bitmask newNotReady; /* Return value */ + int iReleaseReg = 0; /* Temp register to free before returning */ pParse = pWInfo->pParse; v = pParse->pVdbe; - pWC = &pWInfo->sWC; + pWC = pWInfo->pWC; pLevel = &pWInfo->a[iLevel]; - pLoop = pLevel->pWLoop; pTabItem = &pWInfo->pTabList->a[pLevel->iFrom]; iCur = pTabItem->iCursor; - bRev = (pWInfo->revMask>>iLevel)&1; - omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0 - && (pWInfo->wctrlFlags & WHERE_FORCE_TABLE)==0; - VdbeNoopComment((v, "Begin Join Loop %d", iLevel)); + bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0; /* Create labels for the "break" and "continue" instructions ** for the current loop. Jump to addrBrk to break out of a loop. ** Jump to cont to go immediately to the next iteration of the ** loop. @@ -3377,77 +3892,65 @@ pLevel->iLeftJoin = ++pParse->nMem; sqlite4VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); VdbeComment((v, "init LEFT JOIN no-match flag")); } -#if 0 - /* Special case of a FROM clause subquery implemented as a co-routine */ - if( pTabItem->viaCoroutine ){ - int regYield = pTabItem->regReturn; - sqlite4VdbeAddOp2(v, OP_Integer, pTabItem->addrFillSub-1, regYield); - pLevel->p2 = sqlite4VdbeAddOp1(v, OP_Yield, regYield); - VdbeComment((v, "next row of co-routine %s", pTabItem->pTab->zName)); - sqlite4VdbeAddOp2(v, OP_If, regYield+1, addrBrk); - pLevel->op = OP_Goto; - }else -#endif - - if( (pLoop->wsFlags & WHERE_INDEXED) - && (pLoop->u.btree.pIndex->eIndexType==SQLITE4_INDEX_FTS5) + if( (pLevel->plan.wsFlags & WHERE_INDEXED) + && (pLevel->plan.u.pIdx->eIndexType==SQLITE4_INDEX_FTS5) ){ /* Case -1: An FTS query */ int iTerm; int rMatch; int rFree; - findMatchExpr(pWC, pTabItem, &iTerm); + findMatchExpr(pParse, pWC, pTabItem, &iTerm); rMatch = sqlite4ExprCodeTemp(pParse, pWC->a[iTerm].pExpr->pRight, &rFree); pWC->a[iTerm].wtFlags |= TERM_CODED; sqlite4Fts5CodeQuery(pParse, - pLoop->u.btree.pIndex, pLevel->iIdxCur, addrBrk, rMatch + pLevel->plan.u.pIdx, pLevel->iIdxCur, addrBrk, rMatch ); - sqlite4VdbeChangeP5(v, bRev); sqlite4ReleaseTempReg(pParse, rFree); pLevel->p2 = sqlite4VdbeCurrentAddr(v); sqlite4VdbeAddOp3(v, OP_SeekPk, iCur, 0, pLevel->iIdxCur); pLevel->op = OP_FtsNext; pLevel->p1 = pLevel->iIdxCur; - }else - + }else #ifndef SQLITE4_OMIT_VIRTUALTABLE - if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){ - /* Case 1: The table is a virtual-table. Use the VFilter and VNext + if( (pLevel->plan.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; - int nConstraint = pLoop->nLTerm; + sqlite4_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx; + int nConstraint = pVtabIdx->nConstraint; + struct sqlite4_index_constraint_usage *aUsage = + pVtabIdx->aConstraintUsage; + const struct sqlite4_index_constraint *aConstraint = + pVtabIdx->aConstraint; sqlite4ExprCachePush(pParse); iReg = sqlite4GetTempRange(pParse, nConstraint+2); - addrNotFound = pLevel->addrBrk; + for(j=1; j<=nConstraint; j++){ + for(k=0; ka[iTerm].pExpr->pRight, iReg+j+1); + break; + } + } + if( k==nConstraint ) break; + } + sqlite4VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg); + sqlite4VdbeAddOp2(v, OP_Integer, j-1, iReg+1); + sqlite4VdbeAddOp4(v, OP_VFilter, iCur, addrBrk, iReg, pVtabIdx->idxStr, + pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC); + pVtabIdx->needToFreeIdxStr = 0; for(j=0; jaLTerm[j]; - if( pTerm==0 ) continue; - if( pTerm->eOperator & WO_IN ){ - codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget); - addrNotFound = pLevel->addrNxt; - }else{ - sqlite4ExprCode(pParse, pTerm->pExpr->pRight, iTarget); - } - } - sqlite4VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg); - sqlite4VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1); - sqlite4VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, - pLoop->u.vtab.idxStr, - pLoop->u.vtab.needFree ? P4_DYNAMIC : P4_STATIC); - pLoop->u.vtab.needFree = 0; - for(j=0; ju.vtab.omitMask>>j)&1 ){ - disableTerm(pLevel, pLoop->aLTerm[j]); + if( aUsage[j].omit ){ + int iTerm = aConstraint[j].iTermOffset; + disableTerm(pLevel, &pWC->a[iTerm]); } } pLevel->op = OP_VNext; pLevel->p1 = iCur; pLevel->p2 = sqlite4VdbeCurrentAddr(v); @@ -3454,12 +3957,12 @@ sqlite4ReleaseTempRange(pParse, iReg, nConstraint+2); sqlite4ExprCachePop(pParse, 1); }else #endif /* SQLITE4_OMIT_VIRTUALTABLE */ - if( pLoop->wsFlags & WHERE_INDEXED ){ - /* Case 4: A scan using an index. + if( pLevel->plan.wsFlags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){ + /* Case 3: A scan using an index. ** ** The WHERE clause may contain zero or more equality ** terms ("==" or "IN" operators) that refer to the N ** left-most columns of the index. It may also contain ** inequality constraints (>, <, >= or <=) on the indexed @@ -3504,12 +4007,12 @@ OP_IdxLE, /* 2: (end_constraints && !endEq && bRev) */ OP_IdxGT, /* 3: (end_constraints && endEq && !bRev) */ OP_IdxLT /* 4: (end_constraints && endEq && bRev) */ }; - int nEq = pLoop->u.btree.nEq; /* Number of == or IN terms */ - int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */ + int nEq = pLevel->plan.nEq; /* Number of == or IN terms */ + int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */ int regBase; /* Base register holding constraint values */ int r1; /* Temp register */ WhereTerm *pRangeStart = 0; /* Inequality constraint at range start */ WhereTerm *pRangeEnd = 0; /* Inequality constraint at range end */ int startEq; /* True if range start uses ==, >= or <= */ @@ -3524,11 +4027,11 @@ char *zEndAff; /* Affinity for end of range constraint */ int regEndKey; /* Register for end-key */ int iIneq; /* The table column subject to inequality */ Index *pPk; /* Primary key index on same table as pIdx */ - pIdx = pLoop->u.btree.pIndex; + pIdx = pLevel->plan.u.pIdx; pPk = sqlite4FindPrimaryKey(pIdx->pTable, 0); iIneq = idxColumnNumber(pIdx, pPk, nEq); iIdxCur = pLevel->iIdxCur; assert( iCur==pLevel->iTabCur ); @@ -3538,56 +4041,57 @@ ** a single iteration. This means that the first row returned ** should not have a NULL value stored in 'x'. If column 'x' is ** the first one after the nEq equality constraints in the index, ** this requires some special handling. */ - if( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0 - && (pWInfo->bOBSat!=0) + if( (wctrlFlags&WHERE_ORDERBY_MIN)!=0 + && (pLevel->plan.wsFlags&WHERE_ORDERBY) && (pIdx->nColumn>nEq) ){ /* assert( pOrderBy->nExpr==1 ); */ /* assert( pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq] ); */ isMinQuery = 1; nExtraReg = 1; } /* Find any inequality constraint terms for the start and end - ** of the range. - */ - j = nEq; - if( pLoop->wsFlags & WHERE_BTM_LIMIT ){ - pRangeStart = pLoop->aLTerm[j++]; + ** of the range. */ + if( pLevel->plan.wsFlags & WHERE_TOP_LIMIT ){ + pRangeEnd = findTerm(pWC, iCur, iIneq, notReady, (WO_LT|WO_LE), pIdx); nExtraReg = 1; } - if( pLoop->wsFlags & WHERE_TOP_LIMIT ){ - pRangeEnd = pLoop->aLTerm[j++]; + if( pLevel->plan.wsFlags & WHERE_BTM_LIMIT ){ + pRangeStart = findTerm(pWC, iCur, iIneq, notReady, (WO_GT|WO_GE), pIdx); nExtraReg = 1; } /* Generate code to evaluate all constraint terms using == or IN ** and store the values of those terms in an array of registers - ** starting at regBase. + ** starting at regBase. Ensure that nExtraReg registers are allocated + ** immediately following the array. */ - regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff); + regBase = codeAllEqualityTerms( + pParse, pLevel, pWC, notReady, nExtraReg, &zStartAff + ); assert( (regBase+nEq+nExtraReg-1)<=pParse->nMem ); + zEndAff = sqlite4DbStrDup(pParse->db, zStartAff); addrNxt = pLevel->addrNxt; /* If we are doing a reverse order scan on an ascending index, or ** a forward order scan on a descending index, interchange the - ** start and end terms (pRangeStart and pRangeEnd). - */ + ** start and end terms (pRangeStart and pRangeEnd). */ if( (nEqnColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE4_SO_ASC)) || (bRev && pIdx->nColumn==nEq) ){ SWAP(WhereTerm *, pRangeEnd, pRangeStart); } - testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 ); - testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 ); - testcase( pRangeEnd && (pRangeEnd->eOperator & WO_LE)!=0 ); - testcase( pRangeEnd && (pRangeEnd->eOperator & WO_GE)!=0 ); + testcase( pRangeStart && pRangeStart->eOperator & WO_LE ); + testcase( pRangeStart && pRangeStart->eOperator & WO_GE ); + testcase( pRangeEnd && pRangeEnd->eOperator & WO_LE ); + testcase( pRangeEnd && pRangeEnd->eOperator & WO_GE ); startEq = !pRangeStart || pRangeStart->eOperator & (WO_LE|WO_GE); endEq = !pRangeEnd || pRangeEnd->eOperator & (WO_LE|WO_GE); start_constraints = pRangeStart || nEq>0; /* Seek the index cursor to the start of the range. */ @@ -3625,11 +4129,11 @@ testcase( op==OP_SeekGt ); testcase( op==OP_SeekGe ); testcase( op==OP_SeekLe ); testcase( op==OP_SeekLt ); sqlite4VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); - if( nEqnColumn + (pIdx==pPk ? 0 : pPk->nColumn))>nEq ){ sqlite4VdbeChangeP5(v, OPFLAG_PARTIALKEY); } /* Set variable op to the instruction required to determine if the ** cursor is passed the end of the range. If the range is unbounded, @@ -3641,13 +4145,12 @@ testcase( op==OP_IdxLT ); testcase( op==OP_IdxLE ); testcase( op==OP_IdxGT ); if( op!=OP_Noop ){ - /* Load the value for the inequality constraint at the end of the - ** range (if any). - */ + /* If there is an inequality at the end of this range, compute its + ** value here. */ nConstraint = nEq; if( pRangeEnd ){ Expr *pRight = pRangeEnd->pExpr->pRight; sqlite4ExprCacheRemove(pParse, regBase+nEq, 1); sqlite4ExprCode(pParse, pRight, regBase+nEq); @@ -3655,12 +4158,12 @@ sqlite4ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt); } if( zEndAff ){ if( sqlite4CompareAffinity(pRight, zEndAff[nEq])==SQLITE4_AFF_NONE){ /* Since the comparison is to be performed with no conversions - ** applied to the operands, set the affinity to apply to pRight to - ** SQLITE4_AFF_NONE. */ + ** applied to the operands, set the affinity to apply to pRight to + ** SQLITE4_AFF_NONE. */ zEndAff[nEq] = SQLITE4_AFF_NONE; } if( sqlite4ExprNeedsNoAffinityChange(pRight, zEndAff[nEq]) ){ zEndAff[nEq] = SQLITE4_AFF_NONE; } @@ -3670,19 +4173,13 @@ testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ } /* Now compute an end-key using OP_MakeIdxKey */ regEndKey = ++pParse->nMem; - if( pIdx->tnum==KVSTORE_ROOT ){ - sqlite4VdbeAddOp2(v, OP_Copy, regBase, regEndKey); - sqlite4VdbeAddOp1(v, OP_ToBlob, regEndKey); - }else{ - sqlite4VdbeAddOp4Int( - v, OP_MakeIdxKey, iIdxCur, regBase, regEndKey, nConstraint - ); - } - + sqlite4VdbeAddOp4Int( + v, OP_MakeIdxKey, iIdxCur, regBase, regEndKey, nConstraint + ); } sqlite4DbFree(pParse->db, zStartAff); sqlite4DbFree(pParse->db, zEndAff); @@ -3696,49 +4193,43 @@ /* Seek the PK cursor, if required */ disableTerm(pLevel, pRangeStart); disableTerm(pLevel, pRangeEnd); if( pIdx->eIndexType!=SQLITE4_INDEX_PRIMARYKEY && pIdx->eIndexType!=SQLITE4_INDEX_TEMP - && 0==(pLoop->wsFlags & WHERE_IDX_ONLY) ){ sqlite4VdbeAddOp3(v, OP_SeekPk, iCur, 0, iIdxCur); } /* If there are inequality constraints, check that the value - ** of the table column that the inequality contrains is not NULL. - ** If it is, jump to the next iteration of the loop. - */ + ** of the table column that the inequality constrains is not NULL. + ** If it is, jump to the next iteration of the loop. */ r1 = sqlite4GetTempReg(pParse); - testcase( pLoop->wsFlags & WHERE_BTM_LIMIT ); - testcase( pLoop->wsFlags & WHERE_TOP_LIMIT ); - if( (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 ){ + testcase( pLevel->plan.wsFlags & WHERE_BTM_LIMIT ); + testcase( pLevel->plan.wsFlags & WHERE_TOP_LIMIT ); + if( (pLevel->plan.wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 ){ sqlite4ExprCodeGetColumnOfTable(v, pIdx->pTable, iCur, iIneq, r1); sqlite4VdbeAddOp2(v, OP_IsNull, r1, addrCont); } sqlite4ReleaseTempReg(pParse, r1); /* Record the instruction used to terminate the loop. Disable ** WHERE clause terms made redundant by the index range scan. */ - if( pLoop->wsFlags & WHERE_ONEROW ){ + if( pLevel->plan.wsFlags & WHERE_UNIQUE ){ pLevel->op = OP_Noop; }else if( bRev ){ pLevel->op = OP_Prev; }else{ pLevel->op = OP_Next; } pLevel->p1 = iIdxCur; - if( (pLoop->wsFlags & WHERE_CONSTRAINT)==0 ){ - pLevel->p5 = SQLITE4_STMTSTATUS_FULLSCAN_STEP; - }else{ - assert( pLevel->p5==0 ); - } + }else #ifndef SQLITE4_OMIT_OR_OPTIMIZATION - if( pLoop->wsFlags & WHERE_MULTI_OR ){ - /* Case 5: Two or more separately indexed terms connected by OR + if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){ + /* Case 4: Two or more separately indexed terms connected by OR ** ** Example: ** ** CREATE TABLE t1(a,b,c,d); ** CREATE INDEX i1 ON t1(a); @@ -3775,12 +4266,10 @@ ** B: ** */ WhereClause *pOrWc; /* The OR-clause broken out into subterms */ SrcList *pOrTab; /* Shortened table list or OR-clause generation */ - Index *pCov = 0; /* Potential covering index (or NULL) */ - int iCovCur = pParse->nTab++; /* Cursor used for index scans (if any) */ int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */ int regKeyset = 0; /* Register for RowSet object */ int regKey = 0; /* Register holding key */ int iLoopBody = sqlite4VdbeMakeLabel(v); /* Start of loop body */ @@ -3787,13 +4276,13 @@ int iRetInit; /* Address of regReturn init */ int untestedTerms = 0; /* Some terms not completely tested */ int ii; /* Loop counter */ Expr *pAndExpr = 0; /* An ".. AND (...)" expression */ - pTerm = pLoop->aLTerm[0]; + pTerm = pLevel->plan.u.pTerm; assert( pTerm!=0 ); - assert( pTerm->eOperator & WO_OR ); + assert( pTerm->eOperator==WO_OR ); assert( (pTerm->wtFlags & TERM_ORINFO)!=0 ); pOrWc = &pTerm->u.pOrInfo->wc; pLevel->op = OP_Return; pLevel->p1 = regReturn; @@ -3801,16 +4290,16 @@ ** by this loop in the a[0] slot and all notReady tables in a[1..] slots. ** This becomes the SrcList in the recursive call to sqlite4WhereBegin(). */ if( pWInfo->nLevel>1 ){ int nNotReady; /* The number of notReady tables */ - struct SrcListItem *origSrc; /* Original list of tables */ + SrcListItem *origSrc; /* Original list of tables */ nNotReady = pWInfo->nLevel - iLevel - 1; pOrTab = sqlite4StackAllocRaw(pParse->db, sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0])); if( pOrTab==0 ) return notReady; - pOrTab->nAlloc = (u8)(nNotReady + 1); + pOrTab->nAlloc = (i16)(nNotReady + 1); pOrTab->nSrc = pOrTab->nAlloc; memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem)); origSrc = pWInfo->pTabList->a; for(k=1; k<=nNotReady; k++){ memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k])); @@ -3818,21 +4307,21 @@ }else{ pOrTab = pWInfo->pTabList; } /* Initialize the keyset register to contain NULL. An SQL NULL is - ** equivalent to an empty keyset. + ** equivalent to an empty rowset. ** ** Also initialize regReturn to contain the address of the instruction ** immediately following the OP_Return at the bottom of the loop. This ** is required in a few obscure LEFT JOIN cases where control jumps ** over the top of the loop into the body of it. In this case the ** correct response for the end-of-loop code (the OP_Return) is to ** fall through to the next instruction, just as an OP_Next does if ** called on an uninitialized cursor. */ - if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ + if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ regKeyset = ++pParse->nMem; regKey = ++pParse->nMem; sqlite4VdbeAddOp2(v, OP_Null, 0, regKeyset); } iRetInit = sqlite4VdbeAddOp2(v, OP_Integer, 0, regReturn); @@ -3839,60 +4328,40 @@ /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y ** Then for every term xN, evaluate as the subexpression: xN AND z ** That way, terms in y that are factored into the disjunction will ** be picked up by the recursive calls to sqlite4WhereBegin() below. - ** - ** Actually, each subexpression is converted to "xN AND w" where w is - ** the "interesting" terms of z - terms that did not originate in the - ** ON or USING clause of a LEFT JOIN, and terms that are usable as - ** indices. - ** - ** This optimization also only applies if the (x1 OR x2 OR ...) term - ** is not contained in the ON clause of a LEFT JOIN. - ** See ticket http://www.sqlite.org/src/info/f2369304e4 */ if( pWC->nTerm>1 ){ - int iTerm; - for(iTerm=0; iTermnTerm; iTerm++){ - Expr *pExpr = pWC->a[iTerm].pExpr; - if( &pWC->a[iTerm] == pTerm ) continue; - if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; - if( pWC->a[iTerm].wtFlags & (TERM_ORINFO) ) continue; - if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; - pExpr = sqlite4ExprDup(pParse->db, pExpr, 0); - pAndExpr = sqlite4ExprAnd(pParse->db, pAndExpr, pExpr); - } - if( pAndExpr ){ - pAndExpr = sqlite4PExpr(pParse, TK_AND, 0, pAndExpr, 0); - } + pAndExpr = sqlite4ExprAlloc(pParse->db, TK_AND, 0, 0); + pAndExpr->pRight = pWhere; } for(ii=0; iinTerm; ii++){ WhereTerm *pOrTerm = &pOrWc->a[ii]; - if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){ + if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){ WhereInfo *pSubWInfo; /* Info for single OR-term scan */ Expr *pOrExpr = pOrTerm->pExpr; - if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){ + if( pAndExpr ){ pAndExpr->pLeft = pOrExpr; pOrExpr = pAndExpr; } /* Loop through table entries that match term pOrTerm. */ pSubWInfo = sqlite4WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY | - WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur); - assert( pSubWInfo || pParse->nErr || pParse->db->mallocFailed ); + WHERE_NO_AUTOINDEX | WHERE_ONETABLE_ONLY); if( pSubWInfo ){ - WhereLoop *pSubLoop; explainOneScan( pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0 ); - if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ - int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); + if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ + int addrJump; sqlite4VdbeAddOp2(v, OP_RowKey, iCur, regKey); - sqlite4VdbeAddOp4Int(v, OP_RowSetTest, regKeyset, - sqlite4VdbeCurrentAddr(v)+2, regKey, iSet); + addrJump = sqlite4VdbeCurrentAddr(v) + 2; + sqlite4VdbeAddOp4Int(v, OP_RowSetTest, + regKeyset, addrJump, regKey, ((ii==pOrWc->nTerm-1)?-1:ii) + ); } sqlite4VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody); /* The pSubWInfo->untestedTerms flag means that this OR term ** contained one or more AND term from a notReady table. The @@ -3899,49 +4368,16 @@ ** terms from the notReady table could not be tested and will ** need to be tested later. */ if( pSubWInfo->untestedTerms ) untestedTerms = 1; - /* If all of the OR-connected terms are optimized using the same - ** index, and the index is opened using the same cursor number - ** by each call to sqlite4WhereBegin() made by this loop, it may - ** be possible to use that index as a covering index. - ** - ** If the call to sqlite4WhereBegin() above resulted in a scan that - ** uses an index, and this is either the first OR-connected term - ** processed or the index is the same as that used by all previous - ** terms, set pCov to the candidate covering index. Otherwise, set - ** pCov to NULL to indicate that no candidate covering index will - ** be available. - */ - pSubLoop = pSubWInfo->a[0].pWLoop; - assert( (pSubLoop->wsFlags & WHERE_AUTO_INDEX)==0 ); - if( (pSubLoop->wsFlags & WHERE_INDEXED)!=0 - && (ii==0 || pSubLoop->u.btree.pIndex==pCov) - ){ - pCov = pSubLoop->u.btree.pIndex; - assert( pCov->eIndexType==SQLITE4_INDEX_PRIMARYKEY - || pSubWInfo->a[0].iIdxCur==iCovCur - ); - }else{ - pCov = 0; - } - /* Finish the loop through table entries that match term pOrTerm. */ sqlite4WhereEnd(pSubWInfo); } } } - assert( pLevel->u.pCovidx==0 ); - if( pCov && pCov->eIndexType!=SQLITE4_INDEX_PRIMARYKEY ){ - pLevel->iIdxCur = iCovCur; - pLevel->u.pCovidx = pCov; - } - if( pAndExpr ){ - pAndExpr->pLeft = 0; - sqlite4ExprDelete(pParse->db, pAndExpr); - } + sqlite4DbFree(pParse->db, pAndExpr); sqlite4VdbeChangeP1(v, iRetInit, sqlite4VdbeCurrentAddr(v)); sqlite4VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk); sqlite4VdbeResolveLabel(v, iLoopBody); if( pWInfo->nLevel>1 ) sqlite4StackFree(pParse->db, pOrTab); @@ -3948,24 +4384,22 @@ if( !untestedTerms ) disableTerm(pLevel, pTerm); }else #endif /* SQLITE4_OMIT_OR_OPTIMIZATION */ { - /* Case 6: There is no usable index. We must do a complete - ** scan of the entire table. This comes up when scanning - ** through b-trees containing materialized sub-queries or - ** views. + /* Case 5: There is no usable index. We must do a complete + ** scan of the entire table. */ static const u8 aStep[] = { OP_Next, OP_Prev }; static const u8 aStart[] = { OP_Rewind, OP_Last }; assert( bRev==0 || bRev==1 ); pLevel->op = aStep[bRev]; pLevel->p1 = iCur; pLevel->p2 = 1 + sqlite4VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); pLevel->p5 = SQLITE4_STMTSTATUS_FULLSCAN_STEP; } - newNotReady = notReady & ~getMask(&pWInfo->sMaskSet, iCur); + notReady &= ~getMask(pWC->pMaskSet, iCur); /* Insert code to test every subexpression that can be completely ** computed using the current set of tables. ** ** IMPLEMENTATION-OF: R-49525-50935 Terms that cannot be satisfied through @@ -3975,11 +4409,11 @@ for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ Expr *pE; testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */ testcase( pTerm->wtFlags & TERM_CODED ); if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; - if( (pTerm->prereqAll & newNotReady)!=0 ){ + if( (pTerm->prereqAll & notReady)!=0 ){ testcase( pWInfo->untestedTerms==0 && (pWInfo->wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ); pWInfo->untestedTerms = 1; continue; } @@ -3990,40 +4424,10 @@ } sqlite4ExprIfFalse(pParse, pE, addrCont, SQLITE4_JUMPIFNULL); pTerm->wtFlags |= TERM_CODED; } - /* Insert code to test for implied constraints based on transitivity - ** of the "==" operator. - ** - ** Example: If the WHERE clause contains "t1.a=t2.b" and "t2.b=123" - ** and we are coding the t1 loop and the t2 loop has not yet coded, - ** then we cannot use the "t1.a=t2.b" constraint, but we can code - ** the implied "t1.a=123" constraint. - */ - for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ - Expr *pE; - WhereTerm *pAlt; - Expr sEq; - if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; - if( pTerm->eOperator!=(WO_EQUIV|WO_EQ) ) continue; - if( pTerm->leftCursor!=iCur ) continue; - if( pLevel->iLeftJoin ) continue; - pE = pTerm->pExpr; - assert( !ExprHasProperty(pE, EP_FromJoin) ); - assert( (pTerm->prereqRight & newNotReady)!=0 ); - pAlt = findTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN, 0); - if( pAlt==0 ) continue; - if( pAlt->wtFlags & (TERM_CODED) ) continue; - testcase( pAlt->eOperator & WO_EQ ); - testcase( pAlt->eOperator & WO_IN ); - VdbeNoopComment((v, "begin transitive constraint")); - sEq = *pAlt->pExpr; - sEq.pLeft = pE->pLeft; - sqlite4ExprIfFalse(pParse, &sEq, addrCont, SQLITE4_JUMPIFNULL); - } - /* For a LEFT OUTER JOIN, generate code that will record the fact that ** at least one row of the right table has matched the left table. */ if( pLevel->iLeftJoin ){ pLevel->addrFirst = sqlite4VdbeCurrentAddr(v); @@ -4032,11 +4436,11 @@ sqlite4ExprCacheClear(pParse); for(pTerm=pWC->a, j=0; jnTerm; j++, pTerm++){ testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */ testcase( pTerm->wtFlags & TERM_CODED ); if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; - if( (pTerm->prereqAll & newNotReady)!=0 ){ + if( (pTerm->prereqAll & notReady)!=0 ){ assert( pWInfo->untestedTerms ); continue; } assert( pTerm->pExpr ); sqlite4ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE4_JUMPIFNULL); @@ -4043,1626 +4447,55 @@ pTerm->wtFlags |= TERM_CODED; } } sqlite4ReleaseTempReg(pParse, iReleaseReg); - return newNotReady; -} - -#ifdef WHERETRACE_ENABLED -/* -** Print a WhereLoop object for debugging purposes -*/ -static void whereLoopPrint(WhereLoop *p, SrcList *pTabList){ - int nb = 1+(pTabList->nSrc+7)/8; - struct SrcListItem *pItem = pTabList->a + p->iTab; - Table *pTab = pItem->pTab; - sqlite4DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId, - p->iTab, nb, p->maskSelf, nb, p->prereq); - sqlite4DebugPrintf(" %12s", - pItem->zAlias ? pItem->zAlias : pTab->zName); - if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ - if( p->u.btree.pIndex ){ - const char *zName = p->u.btree.pIndex->zName; - if( zName==0 ) zName = "ipk"; - if( strncmp(zName, "sqlite_autoindex_", 17)==0 ){ - int i = sqlite4Strlen30(zName) - 1; - while( zName[i]!='_' ) i--; - zName += i; - } - sqlite4DebugPrintf(".%-16s %2d", zName, p->u.btree.nEq); - }else{ - sqlite4DebugPrintf("%20s",""); - } - }else{ - char *z; - if( p->u.vtab.idxStr ){ - z = sqlite4_mprintf(0, "(%d,\"%s\",%x)", - p->u.vtab.idxNum, p->u.vtab.idxStr, p->u.vtab.omitMask); - }else{ - z = sqlite4_mprintf(0, "(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask); - } - sqlite4DebugPrintf(" %-19s", z); - sqlite4_free(0, z); - } - sqlite4DebugPrintf(" f %04x N %d", p->wsFlags, p->nLTerm); - sqlite4DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut); -} -#endif - -/* -** Convert bulk memory into a valid WhereLoop that can be passed -** to whereLoopClear harmlessly. -*/ -static void whereLoopInit(WhereLoop *p){ - p->aLTerm = p->aLTermSpace; - p->nLTerm = 0; - p->nLSlot = ArraySize(p->aLTermSpace); - p->wsFlags = 0; -} - -/* -** Clear the WhereLoop.u union. Leave WhereLoop.pLTerm intact. -*/ -static void whereLoopClearUnion(sqlite4 *db, WhereLoop *p){ - if( p->wsFlags & (WHERE_VIRTUALTABLE|WHERE_AUTO_INDEX) ){ - if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 && p->u.vtab.needFree ){ -#if 0 - sqlite4_free(p->u.vtab.idxStr); -#endif - p->u.vtab.needFree = 0; - p->u.vtab.idxStr = 0; - }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){ - sqlite4DbFree(db, p->u.btree.pIndex->zColAff); - sqlite4DbFree(db, p->u.btree.pIndex); - p->u.btree.pIndex = 0; - } - } -} - -/* -** Deallocate internal memory used by a WhereLoop object -*/ -static void whereLoopClear(sqlite4 *db, WhereLoop *p){ - if( p->aLTerm!=p->aLTermSpace ) sqlite4DbFree(db, p->aLTerm); - whereLoopClearUnion(db, p); - whereLoopInit(p); -} - -/* -** Increase the memory allocation for pLoop->aLTerm[] to be at least n. -*/ -static int whereLoopResize(sqlite4 *db, WhereLoop *p, int n){ - WhereTerm **paNew; - if( p->nLSlot>=n ) return SQLITE4_OK; - n = (n+7)&~7; - paNew = sqlite4DbMallocRaw(db, sizeof(p->aLTerm[0])*n); - if( paNew==0 ) return SQLITE4_NOMEM; - memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot); - if( p->aLTerm!=p->aLTermSpace ) sqlite4DbFree(db, p->aLTerm); - p->aLTerm = paNew; - p->nLSlot = n; - return SQLITE4_OK; -} - -/* -** Transfer content from the second pLoop into the first. -*/ -static int whereLoopXfer(sqlite4 *db, WhereLoop *pTo, WhereLoop *pFrom){ - if( whereLoopResize(db, pTo, pFrom->nLTerm) ) return SQLITE4_NOMEM; - whereLoopClearUnion(db, pTo); - memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ); - memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0])); - if( pFrom->wsFlags & WHERE_VIRTUALTABLE ){ - pFrom->u.vtab.needFree = 0; - }else if( (pFrom->wsFlags & WHERE_AUTO_INDEX)!=0 ){ - pFrom->u.btree.pIndex = 0; - } - return SQLITE4_OK; -} - -/* -** Delete a WhereLoop object -*/ -static void whereLoopDelete(sqlite4 *db, WhereLoop *p){ - whereLoopClear(db, p); - sqlite4DbFree(db, p); -} + return notReady; +} + +#if defined(SQLITE4_TEST) +/* +** The following variable holds a text description of query plan generated +** by the most recent call to sqlite4WhereBegin(). Each call to WhereBegin +** overwrites the previous. This information is used for testing and +** analysis only. +*/ +char sqlite4_query_plan[BMS*2*40]; /* Text of the join */ +static int nQPlan = 0; /* Next free slow in _query_plan[] */ + +#endif /* SQLITE4_TEST */ + /* ** Free a WhereInfo structure */ static void whereInfoFree(sqlite4 *db, WhereInfo *pWInfo){ if( ALWAYS(pWInfo) ){ - whereClauseClear(&pWInfo->sWC); - while( pWInfo->pLoops ){ - WhereLoop *p = pWInfo->pLoops; - pWInfo->pLoops = p->pNextLoop; - whereLoopDelete(db, p); + int i; + for(i=0; inLevel; i++){ + sqlite4_index_info *pInfo = pWInfo->a[i].pIdxInfo; + if( pInfo ){ + /* assert( pInfo->needToFreeIdxStr==0 || db->mallocFailed ); */ + if( pInfo->needToFreeIdxStr ){ + sqlite4_free(db->pEnv, pInfo->idxStr); + } + sqlite4DbFree(db, pInfo); + } + if( pWInfo->a[i].plan.wsFlags & WHERE_TEMP_INDEX ){ + Index *pIdx = pWInfo->a[i].plan.u.pIdx; + if( pIdx ){ + assert( pIdx->eIndexType==SQLITE4_INDEX_TEMP ); + sqlite4DbFree(db, pIdx->zColAff); + sqlite4DbFree(db, pIdx); + } + } } + whereClauseClear(pWInfo->pWC); sqlite4DbFree(db, pWInfo); } } -/* -** Insert or replace a WhereLoop entry using the template supplied. -** -** An existing WhereLoop entry might be overwritten if the new template -** is better and has fewer dependencies. Or the template will be ignored -** and no insert will occur if an existing WhereLoop is faster and has -** fewer dependencies than the template. Otherwise a new WhereLoop is -** added based on the template. -** -** If pBuilder->pOrSet is not NULL then we only care about only the -** prerequisites and rRun and nOut costs of the N best loops. That -** information is gathered in the pBuilder->pOrSet object. This special -** processing mode is used only for OR clause processing. -** -** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we -** still might overwrite similar loops with the new template if the -** template is better. Loops may be overwritten if the following -** conditions are met: -** -** (1) They have the same iTab. -** (2) They have the same iSortIdx. -** (3) The template has same or fewer dependencies than the current loop -** (4) The template has the same or lower cost than the current loop -** (5) The template uses more terms of the same index but has no additional -** dependencies -*/ -static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ - WhereLoop **ppPrev, *p, *pNext = 0; - WhereInfo *pWInfo = pBuilder->pWInfo; - sqlite4 *db = pWInfo->pParse->db; - - assert( pTemplate->u.btree.pIndex || !(pTemplate->wsFlags & WHERE_INDEXED) ); - - /* If pBuilder->pOrSet is defined, then only keep track of the costs - ** and prereqs. - */ - if( pBuilder->pOrSet!=0 ){ -#if WHERETRACE_ENABLED - u16 n = pBuilder->pOrSet->n; - int x = -#endif - whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun, - pTemplate->nOut); -#if WHERETRACE_ENABLED - if( sqlite4WhereTrace & 0x8 ){ - - sqlite4DebugPrintf(x?" or-%d: ":" or-X: ", n); - whereLoopPrint(pTemplate, pWInfo->pTabList); - } -#endif - return SQLITE4_OK; - } - - /* Search for an existing WhereLoop to overwrite, or which takes - ** priority over pTemplate. - */ - for(ppPrev=&pWInfo->pLoops, p=*ppPrev; p; ppPrev=&p->pNextLoop, p=*ppPrev){ - if( p->iTab!=pTemplate->iTab || p->iSortIdx!=pTemplate->iSortIdx ){ - /* If either the iTab or iSortIdx values for two WhereLoop are different - ** then those WhereLoops need to be considered separately. Neither is - ** a candidate to replace the other. */ - continue; - } - /* In the current implementation, the rSetup value is either zero - ** or the cost of building an automatic index (NlogN) and the NlogN - ** is the same for compatible WhereLoops. */ - assert( p->rSetup==0 || pTemplate->rSetup==0 - || p->rSetup==pTemplate->rSetup ); - - /* whereLoopAddBtree() always generates and inserts the automatic index - ** case first. Hence compatible candidate WhereLoops never have a larger - ** rSetup. Call this SETUP-INVARIANT */ - assert( p->rSetup>=pTemplate->rSetup ); - - if( (p->prereq & pTemplate->prereq)==p->prereq - && p->rSetup<=pTemplate->rSetup - && p->rRun<=pTemplate->rRun - ){ - /* This branch taken when p is equal or better than pTemplate in - ** all of (1) dependences (2) setup-cost, and (3) run-cost. */ - assert( p->rSetup==pTemplate->rSetup ); - if( p->nLTermnLTerm - && (p->wsFlags & WHERE_INDEXED)!=0 - && (pTemplate->wsFlags & WHERE_INDEXED)!=0 - && p->u.btree.pIndex==pTemplate->u.btree.pIndex - && p->prereq==pTemplate->prereq - ){ - /* Overwrite an existing WhereLoop with an similar one that uses - ** more terms of the index */ - pNext = p->pNextLoop; - break; - }else{ - /* pTemplate is not helpful. - ** Return without changing or adding anything */ - goto whereLoopInsert_noop; - } - } - if( (p->prereq & pTemplate->prereq)==pTemplate->prereq - && p->rRun>=pTemplate->rRun - && ALWAYS(p->rSetup>=pTemplate->rSetup) /* See SETUP-INVARIANT above */ - ){ - /* Overwrite an existing WhereLoop with a better one: one that is - ** better at one of (1) dependences, (2) setup-cost, or (3) run-cost - ** and is no worse in any of those categories. */ - pNext = p->pNextLoop; - break; - } - } - - /* If we reach this point it means that either p[] should be overwritten - ** with pTemplate[] if p[] exists, or if p==NULL then allocate a new - ** WhereLoop and insert it. - */ -#if WHERETRACE_ENABLED - if( sqlite4WhereTrace & 0x8 ){ - if( p!=0 ){ - sqlite4DebugPrintf("ins-del: "); - whereLoopPrint(p, pWInfo->pTabList); - } - sqlite4DebugPrintf("ins-new: "); - whereLoopPrint(pTemplate, pWInfo->pTabList); - } -#endif - if( p==0 ){ - p = sqlite4DbMallocRaw(db, sizeof(WhereLoop)); - if( p==0 ) return SQLITE4_NOMEM; - whereLoopInit(p); - } - whereLoopXfer(db, p, pTemplate); - p->pNextLoop = pNext; - *ppPrev = p; - if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ - Index *pIndex = p->u.btree.pIndex; - if( pIndex && pIndex->tnum==0 ){ - p->u.btree.pIndex = 0; - } - } - return SQLITE4_OK; - - /* Jump here if the insert is a no-op */ -whereLoopInsert_noop: -#if WHERETRACE_ENABLED - if( sqlite4WhereTrace & 0x8 ){ - sqlite4DebugPrintf("ins-noop: "); - whereLoopPrint(pTemplate, pWInfo->pTabList); - } -#endif - return SQLITE4_OK; -} - - -/* -** We have so far matched pBuilder->pNew->u.btree.nEq terms of the index pIndex. -** Try to match one more. -*/ -static int whereLoopAddBtreeIndex( - WhereLoopBuilder *pBuilder, /* The WhereLoop factory */ - struct SrcListItem *pSrc, /* FROM clause term being analyzed */ - Index *pProbe, /* An index on pSrc */ - WhereCost nInMul /* log(Number of iterations due to IN) */ -){ - WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */ - Parse *pParse = pWInfo->pParse; /* Parsing context */ - sqlite4 *db = pParse->db; /* Database connection malloc context */ - WhereLoop *pNew; /* Template WhereLoop under construction */ - WhereTerm *pTerm; /* A WhereTerm under consideration */ - int opMask; /* Valid operators for constraints */ - WhereScan scan; /* Iterator for WHERE terms */ - Bitmask saved_prereq; /* Original value of pNew->prereq */ - u16 saved_nLTerm; /* Original value of pNew->nLTerm */ - int saved_nEq; /* Original value of pNew->u.btree.nEq */ - u32 saved_wsFlags; /* Original value of pNew->wsFlags */ - WhereCost saved_nOut; /* Original value of pNew->nOut */ - int iCol; /* Index of the column in the table */ - int rc = SQLITE4_OK; /* Return code */ - WhereCost nRowEst; /* Estimated index selectivity */ - WhereCost rLogSize; /* Logarithm of table size */ - WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */ - - assert( pProbe->eIndexType==SQLITE4_INDEX_USER - || pProbe->eIndexType==SQLITE4_INDEX_UNIQUE - || pProbe->eIndexType==SQLITE4_INDEX_PRIMARYKEY - ); - - pNew = pBuilder->pNew; - if( db->mallocFailed ) return SQLITE4_NOMEM; - - assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 ); - assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); - if( pNew->wsFlags & WHERE_BTM_LIMIT ){ - opMask = WO_LT|WO_LE; - }else if( pProbe->tnum<=0 || (pSrc->jointype & JT_LEFT)!=0 ){ - opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE; - }else{ - opMask = WO_EQ|WO_IN|WO_ISNULL|WO_GT|WO_GE|WO_LT|WO_LE; - } - if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); - - if( pNew->u.btree.nEq < pProbe->nColumn ){ - iCol = pProbe->aiColumn[pNew->u.btree.nEq]; - nRowEst = whereCost(pProbe->aiRowEst[pNew->u.btree.nEq+1]); - if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1; - }else if( pProbe->eIndexType!=SQLITE4_INDEX_PRIMARYKEY ){ - Index *pPk; - pPk = sqlite4FindPrimaryKey(pProbe->pTable, 0); - iCol = idxColumnNumber(pProbe, pPk, pNew->u.btree.nEq); - nRowEst = 0; - }else{ - return SQLITE4_OK; - } - assert( iCol>=-1 ); - pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, iCol, - opMask, pProbe); - saved_nEq = pNew->u.btree.nEq; - saved_nLTerm = pNew->nLTerm; - saved_wsFlags = pNew->wsFlags; - saved_prereq = pNew->prereq; - saved_nOut = pNew->nOut; - pNew->rSetup = 0; - rLogSize = estLog(whereCost(pProbe->aiRowEst[0])); - for(; rc==SQLITE4_OK && pTerm!=0; pTerm = whereScanNext(&scan)){ - int nIn = 0; - if( pTerm->prereqRight & pNew->maskSelf ) continue; -#ifdef SQLITE4_ENABLE_STAT3 - if( (pTerm->wtFlags & TERM_VNULL)!=0 && pSrc->pTab->aCol[iCol].notNull ){ - continue; /* skip IS NOT NULL constraints on a NOT NULL column */ - } -#endif - pNew->wsFlags = saved_wsFlags; - pNew->u.btree.nEq = saved_nEq; - pNew->nLTerm = saved_nLTerm; - if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ - pNew->aLTerm[pNew->nLTerm++] = pTerm; - pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf; - pNew->rRun = rLogSize; /* Baseline cost is log2(N). Adjustments below */ - if( pTerm->eOperator & WO_IN ){ - Expr *pExpr = pTerm->pExpr; - pNew->wsFlags |= WHERE_COLUMN_IN; - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */ - nIn = 46; assert( 46==whereCost(25) ); - }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ - /* "x IN (value, value, ...)" */ - nIn = whereCost(pExpr->x.pList->nExpr); - } - pNew->rRun += nIn; - pNew->u.btree.nEq++; - pNew->nOut = nRowEst + nInMul + nIn; - }else if( pTerm->eOperator & (WO_EQ) ){ - assert( (pNew->wsFlags & (WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0 - || nInMul==0 ); - pNew->wsFlags |= WHERE_COLUMN_EQ; - if( iCol<0 - || (pProbe->onError!=OE_None && nInMul==0 - && pNew->u.btree.nEq==pProbe->nColumn-1) - ){ - assert( (pNew->wsFlags & WHERE_COLUMN_IN)==0 || iCol<0 ); - pNew->wsFlags |= WHERE_ONEROW; - } - pNew->u.btree.nEq++; - pNew->nOut = nRowEst + nInMul; - }else if( pTerm->eOperator & (WO_ISNULL) ){ - pNew->wsFlags |= WHERE_COLUMN_NULL; - pNew->u.btree.nEq++; - /* TUNING: IS NULL selects 2 rows */ - nIn = 10; assert( 10==whereCost(2) ); - pNew->nOut = nRowEst + nInMul + nIn; - }else if( pTerm->eOperator & (WO_GT|WO_GE) ){ - testcase( pTerm->eOperator & WO_GT ); - testcase( pTerm->eOperator & WO_GE ); - pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT; - pBtm = pTerm; - pTop = 0; - }else{ - assert( pTerm->eOperator & (WO_LT|WO_LE) ); - testcase( pTerm->eOperator & WO_LT ); - testcase( pTerm->eOperator & WO_LE ); - pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT; - pTop = pTerm; - pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ? - pNew->aLTerm[pNew->nLTerm-2] : 0; - } - if( pNew->wsFlags & WHERE_COLUMN_RANGE ){ - /* Adjust nOut and rRun for STAT3 range values */ - WhereCost rDiv; - whereRangeScanEst(pParse, pProbe, pNew->u.btree.nEq, - pBtm, pTop, &rDiv); - pNew->nOut = saved_nOut>rDiv+10 ? saved_nOut - rDiv : 10; - } -#ifdef SQLITE4_ENABLE_STAT3 - if( pNew->u.btree.nEq==1 && pProbe->nSample - && OptimizationEnabled(db, SQLITE4_Stat3) ){ - tRowcnt nOut = 0; - if( (pTerm->eOperator & (WO_EQ|WO_ISNULL))!=0 ){ - testcase( pTerm->eOperator & WO_EQ ); - testcase( pTerm->eOperator & WO_ISNULL ); - rc = whereEqualScanEst(pParse, pProbe, pTerm->pExpr->pRight, &nOut); - }else if( (pTerm->eOperator & WO_IN) - && !ExprHasProperty(pTerm->pExpr, EP_xIsSelect) ){ - rc = whereInScanEst(pParse, pProbe, pTerm->pExpr->x.pList, &nOut); - } - if( rc==SQLITE4_OK ) pNew->nOut = whereCost(nOut); - } -#endif - if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_PRIMARY_KEY))==0 ){ - /* Each row involves a step of the index, then a binary search of - ** the main table */ - pNew->rRun = whereCostAdd(pNew->rRun, rLogSize>27 ? rLogSize-17 : 10); - } - /* Step cost for each output row */ - pNew->rRun = whereCostAdd(pNew->rRun, pNew->nOut); - /* TBD: Adjust nOut for additional constraints */ - rc = whereLoopInsert(pBuilder, pNew); - if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 - && pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0)) - ){ - whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn); - } - } - pNew->prereq = saved_prereq; - pNew->u.btree.nEq = saved_nEq; - pNew->wsFlags = saved_wsFlags; - pNew->nOut = saved_nOut; - pNew->nLTerm = saved_nLTerm; - return rc; -} - -/* -** Return True if it is possible that pIndex might be useful in -** implementing the ORDER BY clause in pBuilder. -** -** Return False if pBuilder does not contain an ORDER BY clause or -** if there is no way for pIndex to be useful in implementing that -** ORDER BY clause. -*/ -static int indexMightHelpWithOrderBy( - WhereLoopBuilder *pBuilder, - Index *pIndex, - int iCursor -){ - ExprList *pOB; - int ii, jj; - - if( pIndex->bUnordered ) return 0; - if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0; - for(ii=0; iinExpr; ii++){ - Expr *pExpr = sqlite4ExprSkipCollate(pOB->a[ii].pExpr); - if( pExpr->op!=TK_COLUMN ) return 0; - if( pExpr->iTable==iCursor ){ - for(jj=0; jjnColumn; jj++){ - if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1; - } - } - } - return 0; -} - -/* -** Return a bitmask where 1s indicate that the corresponding column of -** the table is used by an index. Only the first 63 columns are considered. -*/ -static Bitmask columnsInIndex(Index *pIdx){ - Bitmask m = 0; - if( pIdx->eIndexType!=SQLITE4_INDEX_PRIMARYKEY ){ - int j; - for(j=pIdx->nCover-1; j>=0; j--){ - int x = pIdx->aiCover[j]; - testcase( x==BMS-1 ); - testcase( x==BMS-2 ); - if( xpWC; - int iTerm; - int rc = SQLITE4_OK; - if( findMatchExpr(pWC, pSrc, &iTerm) ){ - WhereLoop *pNew = pBuilder->pNew; - - pNew->prereq = pWC->a[iTerm].prereqRight; - pNew->wsFlags = WHERE_INDEXED; - pNew->rSetup = 0; - pNew->rRun = 1; - pNew->nOut = 1; - pNew->u.btree.nEq = 0; - pNew->u.btree.pIndex = pWC->a[iTerm].pExpr->pIdx; - - rc = whereLoopInsert(pBuilder, pNew); - *pbDone = 1; - }else{ - *pbDone = 0; - } - return rc; -} - -/* -** Add all WhereLoop objects for a single table of the join where the table -** is idenfied by pBuilder->pNew->iTab. That table is guaranteed to be -** a b-tree table, not a virtual table. -*/ -static int whereLoopAddBtree( - WhereLoopBuilder *pBuilder, /* WHERE clause information */ - Bitmask mExtra /* Extra prerequesites for using this table */ -){ - WhereInfo *pWInfo; /* WHERE analysis context */ - Index *pProbe; /* An index we are evaluating */ - Index *pPk; /* Primary key index for table pSrc */ - SrcList *pTabList; /* The FROM clause */ - struct SrcListItem *pSrc; /* The FROM clause btree term to add */ - WhereLoop *pNew; /* Template WhereLoop object */ - int rc = SQLITE4_OK; /* Return code */ - int iSortIdx = 1; /* Index number */ - int b; /* A boolean value */ - WhereCost rSize; /* number of rows in the table */ - WhereCost rLogSize; /* Logarithm of the number of rows in the table */ - - pNew = pBuilder->pNew; - pWInfo = pBuilder->pWInfo; - pTabList = pWInfo->pTabList; - pSrc = pTabList->a + pNew->iTab; - assert( !IsVirtual(pSrc->pTab) ); - pPk = sqlite4FindPrimaryKey(pSrc->pTab, 0); - - if( pSrc->pIndex ){ - /* An INDEXED BY clause specifies a particular index to use */ - pProbe = pSrc->pIndex; - }else if( pSrc->notIndexed ){ - /* A NOT INDEXED clause means use the PK index */ - pProbe = pPk; - }else{ - /* Otherwise, consider all indexes */ - pProbe = pSrc->pTab->pIndex; - } - - rc = whereLoopAddMatch(pBuilder, pSrc, mExtra, &b); - if( b ) return rc; - assert( rc==SQLITE4_OK ); - - rSize = whereCost(pSrc->pTab->nRowEst); - rLogSize = estLog(rSize); - -#ifndef SQLITE4_OMIT_AUTOMATIC_INDEX - /* Automatic indexes */ - if( !pBuilder->pOrSet - && (pWInfo->pParse->db->flags & SQLITE4_AutoIndex)!=0 - && pSrc->pIndex==0 -#if 0 - && !pSrc->viaCoroutine -#endif - && !pSrc->notIndexed - && !pSrc->isCorrelated - ){ - /* Generate auto-index WhereLoops */ - WhereClause *pWC = pBuilder->pWC; - WhereTerm *pTerm; - WhereTerm *pWCEnd = pWC->a + pWC->nTerm; - for(pTerm=pWC->a; rc==SQLITE4_OK && pTermprereqRight & pNew->maskSelf ) continue; - if( termCanDriveIndex(pTerm, pSrc, 0) ){ - pNew->u.btree.nEq = 1; - pNew->u.btree.pIndex = 0; - pNew->nLTerm = 1; - pNew->aLTerm[0] = pTerm; - /* TUNING: One-time cost for computing the automatic index is - ** approximately 7*N*log2(N) where N is the number of rows in - ** the table being indexed. */ - pNew->rSetup = rLogSize + rSize + 28; assert( 28==whereCost(7) ); - /* TUNING: Each index lookup yields 20 rows in the table. This - ** is more than the usual guess of 10 rows, since we have no way - ** of knowning how selective the index will ultimately be. It would - ** not be unreasonable to make this value much larger. */ - pNew->nOut = 43; assert( 43==whereCost(20) ); - pNew->rRun = whereCostAdd(rLogSize,pNew->nOut); - pNew->wsFlags = WHERE_AUTO_INDEX; - pNew->prereq = mExtra | pTerm->prereqRight; - rc = whereLoopInsert(pBuilder, pNew); - } - } - } -#endif /* ifndef SQLITE4_OMIT_AUTOMATIC_INDEX */ - - /* If this table has no primary key, then it is either a materialized - ** view or ephemeral table. Either way, add a WhereLoop for a full-scan - ** of it. */ - if( pPk==0 ){ - assert( pSrc->pTab->pSelect || (pSrc->pTab->tabFlags & TF_Ephemeral) ); - pNew->u.btree.nEq = 0; - pNew->nLTerm = 0; - pNew->iSortIdx = 0; - pNew->rSetup = 0; - pNew->prereq = mExtra; - pNew->nOut = rSize; - pNew->u.btree.pIndex = 0; - pNew->wsFlags = 0; - pNew->rRun = whereCostAdd(rSize,rLogSize) + 16; - rc = whereLoopInsert(pBuilder, pNew); - } - - /* Loop through the set of indices being considered. */ - for(; rc==SQLITE4_OK && pProbe; pProbe=pProbe->pNext, iSortIdx++){ - int bCover = (pProbe!=pPk && 0==(pSrc->colUsed & ~columnsInIndex(pProbe))); - if( pProbe->eIndexType==SQLITE4_INDEX_FTS5 ) continue; - assert( pProbe->tnum>0 ); - - pNew->u.btree.nEq = 0; - pNew->nLTerm = 0; - pNew->rSetup = 0; - pNew->prereq = mExtra; - pNew->nOut = rSize; - pNew->u.btree.pIndex = pProbe; - pNew->wsFlags = WHERE_INDEXED; - pNew->wsFlags |= (bCover ? WHERE_IDX_ONLY : 0); - pNew->wsFlags |= (pProbe==pPk ? WHERE_PRIMARY_KEY : 0); - - b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor); - /* The ONEPASS_DESIRED flags never occurs together with ORDER BY */ - assert( (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || b==0 ); - pNew->iSortIdx = b ? iSortIdx : 0; - - if( pProbe==pPk || b || (bCover - && pProbe->bUnordered==0 - && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 -#if 0 - && sqlite4GlobalConfig.bUseCis - && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan) -#endif - )){ - if( pProbe==pPk ){ - /* TUNING: Cost of full table scan is 3*(N + log2(N)). - ** + The extra 3 factor is to encourage the use of indexed lookups - ** over full scans. A smaller constant 2 is used for covering - ** index scans so that a covering index scan will be favored over - ** a table scan. */ - pNew->rRun = whereCostAdd(rSize,rLogSize) + 16; - }else if( bCover ){ - /* TUNING: Cost of a covering index scan is 2*(N + log2(N)). - ** + The extra 2 factor is to encourage the use of indexed lookups - ** over index scans. A table scan uses a factor of 3 so that - ** index scans are favored over table scans. - ** + If this covering index might also help satisfy the ORDER BY - ** clause, then the cost is fudged down slightly so that this - ** index is favored above other indices that have no hope of - ** helping with the ORDER BY. */ - pNew->rRun = 10 + whereCostAdd(rSize,rLogSize) - b; - }else{ - assert( b!=0 ); - /* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N) - ** which we will simplify to just N*log2(N) */ - pNew->rRun = rSize + rLogSize; - } - rc = whereLoopInsert(pBuilder, pNew); - if( rc ) break; - } - - rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0); - - /* If there was an INDEXED BY or NOT INDEXED clause, then only one - ** index is considered. */ - if( pSrc->pIndex || pSrc->notIndexed ) break; - } - return rc; -} - -#ifndef SQLITE4_OMIT_VIRTUALTABLE -/* -** Add all WhereLoop objects for a table of the join identified by -** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table. -*/ -static int whereLoopAddVirtual( - WhereLoopBuilder *pBuilder /* WHERE clause information */ -){ - WhereInfo *pWInfo; /* WHERE analysis context */ - Parse *pParse; /* The parsing context */ - WhereClause *pWC; /* The WHERE clause */ - struct SrcListItem *pSrc; /* The FROM clause term to search */ - Table *pTab; - sqlite4 *db; - sqlite4_index_info *pIdxInfo; - struct sqlite4_index_constraint *pIdxCons; - struct sqlite4_index_constraint_usage *pUsage; - WhereTerm *pTerm; - int i, j; - int iTerm, mxTerm; - int nConstraint; - int seenIn = 0; /* True if an IN operator is seen */ - int seenVar = 0; /* True if a non-constant constraint is seen */ - int iPhase; /* 0: const w/o IN, 1: const, 2: no IN, 2: IN */ - WhereLoop *pNew; - int rc = SQLITE4_OK; - - pWInfo = pBuilder->pWInfo; - pParse = pWInfo->pParse; - db = pParse->db; - pWC = pBuilder->pWC; - pNew = pBuilder->pNew; - pSrc = &pWInfo->pTabList->a[pNew->iTab]; - pTab = pSrc->pTab; - assert( IsVirtual(pTab) ); - pIdxInfo = allocateIndexInfo(pParse, pWC, pSrc, pBuilder->pOrderBy); - if( pIdxInfo==0 ) return SQLITE4_NOMEM; - pNew->prereq = 0; - pNew->rSetup = 0; - pNew->wsFlags = WHERE_VIRTUALTABLE; - pNew->nLTerm = 0; - pNew->u.vtab.needFree = 0; - pUsage = pIdxInfo->aConstraintUsage; - nConstraint = pIdxInfo->nConstraint; - if( whereLoopResize(db, pNew, nConstraint) ){ - sqlite4DbFree(db, pIdxInfo); - return SQLITE4_NOMEM; - } - - for(iPhase=0; iPhase<=3; iPhase++){ - if( !seenIn && (iPhase&1)!=0 ){ - iPhase++; - if( iPhase>3 ) break; - } - if( !seenVar && iPhase>1 ) break; - pIdxCons = *(struct sqlite4_index_constraint**)&pIdxInfo->aConstraint; - for(i=0; inConstraint; i++, pIdxCons++){ - j = pIdxCons->iTermOffset; - pTerm = &pWC->a[j]; - switch( iPhase ){ - case 0: /* Constants without IN operator */ - pIdxCons->usable = 0; - if( (pTerm->eOperator & WO_IN)!=0 ){ - seenIn = 1; - } - if( pTerm->prereqRight!=0 ){ - seenVar = 1; - }else if( (pTerm->eOperator & WO_IN)==0 ){ - pIdxCons->usable = 1; - } - break; - case 1: /* Constants with IN operators */ - assert( seenIn ); - pIdxCons->usable = (pTerm->prereqRight==0); - break; - case 2: /* Variables without IN */ - assert( seenVar ); - pIdxCons->usable = (pTerm->eOperator & WO_IN)==0; - break; - default: /* Variables with IN */ - assert( seenVar && seenIn ); - pIdxCons->usable = 1; - break; - } - } - memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint); - if( pIdxInfo->needToFreeIdxStr ) sqlite4_free(pIdxInfo->idxStr); - pIdxInfo->idxStr = 0; - pIdxInfo->idxNum = 0; - pIdxInfo->needToFreeIdxStr = 0; - pIdxInfo->orderByConsumed = 0; - pIdxInfo->estimatedCost = SQLITE4_BIG_DBL / (double)2; - rc = vtabBestIndex(pParse, pTab, pIdxInfo); - if( rc ) goto whereLoopAddVtab_exit; - pIdxCons = *(struct sqlite4_index_constraint**)&pIdxInfo->aConstraint; - pNew->prereq = 0; - mxTerm = -1; - assert( pNew->nLSlot>=nConstraint ); - for(i=0; iaLTerm[i] = 0; - pNew->u.vtab.omitMask = 0; - for(i=0; i=0 ){ - j = pIdxCons->iTermOffset; - if( iTerm>=nConstraint - || j<0 - || j>=pWC->nTerm - || pNew->aLTerm[iTerm]!=0 - ){ - rc = SQLITE4_ERROR; - sqlite4ErrorMsg(pParse, "%s.xBestIndex() malfunction", pTab->zName); - goto whereLoopAddVtab_exit; - } - testcase( iTerm==nConstraint-1 ); - testcase( j==0 ); - testcase( j==pWC->nTerm-1 ); - pTerm = &pWC->a[j]; - pNew->prereq |= pTerm->prereqRight; - assert( iTermnLSlot ); - pNew->aLTerm[iTerm] = pTerm; - if( iTerm>mxTerm ) mxTerm = iTerm; - testcase( iTerm==15 ); - testcase( iTerm==16 ); - if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<eOperator & WO_IN)!=0 ){ - if( 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; - } - /* A virtual table that is constrained by an IN clause may not - ** consume the ORDER BY clause because (1) the order of IN terms - ** is not necessarily related to the order of output terms and - ** (2) Multiple outputs from a single IN value will not merge - ** together. */ - pIdxInfo->orderByConsumed = 0; - } - } - } - if( i>=nConstraint ){ - pNew->nLTerm = mxTerm+1; - assert( pNew->nLTerm<=pNew->nLSlot ); - pNew->u.vtab.idxNum = pIdxInfo->idxNum; - pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr; - pIdxInfo->needToFreeIdxStr = 0; - pNew->u.vtab.idxStr = pIdxInfo->idxStr; - pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0) - && pIdxInfo->orderByConsumed); - pNew->rSetup = 0; - pNew->rRun = whereCostFromDouble(pIdxInfo->estimatedCost); - /* TUNING: Every virtual table query returns 25 rows */ - pNew->nOut = 46; assert( 46==whereCost(25) ); - whereLoopInsert(pBuilder, pNew); - if( pNew->u.vtab.needFree ){ - sqlite4_free(pNew->u.vtab.idxStr); - pNew->u.vtab.needFree = 0; - } - } - } - -whereLoopAddVtab_exit: - if( pIdxInfo->needToFreeIdxStr ) sqlite4_free(pIdxInfo->idxStr); - sqlite4DbFree(db, pIdxInfo); - return rc; -} -#endif /* SQLITE4_OMIT_VIRTUALTABLE */ - -/* -** Add WhereLoop entries to handle OR terms. This works for either -** btrees or virtual tables. -*/ -static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){ - WhereInfo *pWInfo = pBuilder->pWInfo; - WhereClause *pWC; - WhereLoop *pNew; - WhereTerm *pTerm, *pWCEnd; - int rc = SQLITE4_OK; - int iCur; - WhereClause tempWC; - WhereLoopBuilder sSubBuild; - WhereOrSet sSum, sCur, sPrev; - struct SrcListItem *pItem; - - pWC = pBuilder->pWC; - if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE4_OK; - pWCEnd = pWC->a + pWC->nTerm; - pNew = pBuilder->pNew; - - for(pTerm=pWC->a; pTermeOperator & WO_OR)!=0 - && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 - ){ - WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; - WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; - WhereTerm *pOrTerm; - int once = 1; - int i, j; - - pItem = pWInfo->pTabList->a + pNew->iTab; - iCur = pItem->iCursor; - sSubBuild = *pBuilder; - sSubBuild.pOrderBy = 0; - sSubBuild.pOrSet = &sCur; - - for(pOrTerm=pOrWC->a; pOrTermeOperator & WO_AND)!=0 ){ - sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc; - }else if( pOrTerm->leftCursor==iCur ){ - tempWC.pWInfo = pWC->pWInfo; - tempWC.pOuter = pWC; - tempWC.op = TK_AND; - tempWC.nTerm = 1; - tempWC.a = pOrTerm; - sSubBuild.pWC = &tempWC; - }else{ - continue; - } - sCur.n = 0; -#ifndef SQLITE4_OMIT_VIRTUALTABLE - if( IsVirtual(pItem->pTab) ){ - rc = whereLoopAddVirtual(&sSubBuild); - for(i=0; inLTerm = 1; - pNew->aLTerm[0] = pTerm; - pNew->wsFlags = WHERE_MULTI_OR; - pNew->rSetup = 0; - pNew->iSortIdx = 0; - memset(&pNew->u, 0, sizeof(pNew->u)); - for(i=0; rc==SQLITE4_OK && irRun = sSum.a[i].rRun + 18; - pNew->nOut = sSum.a[i].nOut; - pNew->prereq = sSum.a[i].prereq; - rc = whereLoopInsert(pBuilder, pNew); - } - } - } - return rc; -} - -/* -** Add all WhereLoop objects for all tables -*/ -static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ - WhereInfo *pWInfo = pBuilder->pWInfo; - Bitmask mExtra = 0; - Bitmask mPrior = 0; - int iTab; - SrcList *pTabList = pWInfo->pTabList; - struct SrcListItem *pItem; - sqlite4 *db = pWInfo->pParse->db; - int nTabList = pWInfo->nLevel; - int rc = SQLITE4_OK; - u8 priorJoinType = 0; - WhereLoop *pNew; - - /* Loop over the tables in the join, from left to right */ - pNew = pBuilder->pNew; - whereLoopInit(pNew); - for(iTab=0, pItem=pTabList->a; iTabiTab = iTab; - pNew->maskSelf = getMask(&pWInfo->sMaskSet, pItem->iCursor); - if( ((pItem->jointype|priorJoinType) & (JT_LEFT|JT_CROSS))!=0 ){ - mExtra = mPrior; - } - priorJoinType = pItem->jointype; -#ifndef SQLITE4_OMIT_VIRTUALTABLE - if( IsVirtual(pItem->pTab) ){ - rc = whereLoopAddVirtual(pBuilder); - }else -#endif - { - rc = whereLoopAddBtree(pBuilder, mExtra); - } - if( rc==SQLITE4_OK ){ - rc = whereLoopAddOr(pBuilder, mExtra); - } - mPrior |= pNew->maskSelf; - if( rc || db->mallocFailed ) break; - } - whereLoopClear(db, pNew); - return rc; -} - -/* -** Examine a WherePath (with the addition of the extra WhereLoop of the 5th -** parameters) to see if it outputs rows in the requested ORDER BY -** (or GROUP BY) without requiring a separate sort operation. Return: -** -** 0: ORDER BY is not satisfied. Sorting required -** 1: ORDER BY is satisfied. Omit sorting -** -1: Unknown at this time -** -** Note that processing for WHERE_GROUPBY and WHERE_DISTINCTBY is not as -** strict. With GROUP BY and DISTINCT the only requirement is that -** equivalent rows appear immediately adjacent to one another. GROUP BY -** and DISTINT do not require rows to appear in any particular order as long -** as equivelent rows are grouped together. Thus for GROUP BY and DISTINCT -** the pOrderBy terms can be matched in any order. With ORDER BY, the -** pOrderBy terms must be matched in strict left-to-right order. -*/ -static int wherePathSatisfiesOrderBy( - WhereInfo *pWInfo, /* The WHERE clause */ - ExprList *pOrderBy, /* ORDER BY or GROUP BY or DISTINCT clause to check */ - WherePath *pPath, /* The WherePath to check */ - u16 wctrlFlags, /* Might contain WHERE_GROUPBY or WHERE_DISTINCTBY */ - u16 nLoop, /* Number of entries in pPath->aLoop[] */ - WhereLoop *pLast, /* Add this WhereLoop to the end of pPath->aLoop[] */ - Bitmask *pRevMask /* OUT: Mask of WhereLoops to run in reverse order */ -){ - u8 revSet; /* True if rev is known */ - u8 rev; /* Composite sort order */ - u8 revIdx; /* Index sort order */ - u8 isOrderDistinct; /* All prior WhereLoops are order-distinct */ - u8 isMatch; /* iColumn matches a term of the ORDER BY clause */ - u16 nColumn; /* Number of columns in pIndex */ - u16 nOrderBy; /* Number terms in the ORDER BY clause */ - int iLoop; /* Index of WhereLoop in pPath being processed */ - int i, j; /* Loop counters */ - int iCur; /* Cursor number for current WhereLoop */ - int iColumn; /* A column number within table iCur */ - WhereLoop *pLoop = 0; /* Current WhereLoop being processed. */ - WhereTerm *pTerm; /* A single term of the WHERE clause */ - Expr *pOBExpr; /* An expression from the ORDER BY clause */ - CollSeq *pColl; /* COLLATE function from an ORDER BY clause term */ - Index *pIndex; /* The index associated with pLoop */ - sqlite4 *db = pWInfo->pParse->db; /* Database connection */ - Bitmask obSat = 0; /* Mask of ORDER BY terms satisfied so far */ - Bitmask obDone; /* Mask of all ORDER BY terms */ - Bitmask orderDistinctMask; /* Mask of all well-ordered loops */ - Bitmask ready; /* Mask of inner loops */ - - /* - ** We say the WhereLoop is "one-row" if it generates no more than one - ** row of output. A WhereLoop is one-row if all of the following are true: - ** (a) All index columns match with WHERE_COLUMN_EQ. - ** (b) The index is unique - ** Any WhereLoop with an WHERE_COLUMN_EQ constraint on the rowid is one-row. - ** Every one-row WhereLoop will have the WHERE_ONEROW bit set in wsFlags. - ** - ** We say the WhereLoop is "order-distinct" if the set of columns from - ** that WhereLoop that are in the ORDER BY clause are different for every - ** row of the WhereLoop. Every one-row WhereLoop is automatically - ** order-distinct. A WhereLoop that has no columns in the ORDER BY clause - ** is not order-distinct. To be order-distinct is not quite the same as being - ** UNIQUE since a UNIQUE column or index can have multiple rows that - ** are NULL and NULL values are equivalent for the purpose of order-distinct. - ** To be order-distinct, the columns must be UNIQUE and NOT NULL. - ** - ** The rowid for a table is always UNIQUE and NOT NULL so whenever the - ** rowid appears in the ORDER BY clause, the corresponding WhereLoop is - ** automatically order-distinct. - */ - - assert( pOrderBy!=0 ); - - /* Sortability of virtual tables is determined by the xBestIndex method - ** of the virtual table itself */ - if( pLast->wsFlags & WHERE_VIRTUALTABLE ){ - testcase( nLoop>0 ); /* True when outer loops are one-row and match - ** no ORDER BY terms */ - return pLast->u.vtab.isOrdered; - } - if( nLoop && OptimizationDisabled(db, SQLITE4_OrderByIdxJoin) ) return 0; - - nOrderBy = pOrderBy->nExpr; - testcase( nOrderBy==BMS-1 ); - if( nOrderBy>BMS-1 ) return 0; /* Cannot optimize overly large ORDER BYs */ - isOrderDistinct = 1; - obDone = MASKBIT(nOrderBy)-1; - orderDistinctMask = 0; - ready = 0; - for(iLoop=0; isOrderDistinct && obSat0 ) ready |= pLoop->maskSelf; - pLoop = iLoopaLoop[iLoop] : pLast; - assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ); - iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor; - - /* Mark off any ORDER BY term X that is a column in the table of - ** the current loop for which there is term in the WHERE - ** clause of the form X IS NULL or X=? that reference only outer - ** loops. - */ - for(i=0; ia[i].pExpr); - if( pOBExpr->op!=TK_COLUMN ) continue; - if( pOBExpr->iTable!=iCur ) continue; - pTerm = findTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn, - ~ready, WO_EQ|WO_ISNULL, 0); - if( pTerm==0 ) continue; - if( (pTerm->eOperator&WO_EQ)!=0 && pOBExpr->iColumn>=0 ){ - const char *z1, *z2; - pColl = sqlite4ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); - if( !pColl ) pColl = db->pDfltColl; - z1 = pColl->zName; - pColl = sqlite4ExprCollSeq(pWInfo->pParse, pTerm->pExpr); - if( !pColl ) pColl = db->pDfltColl; - z2 = pColl->zName; - if( sqlite4_stricmp(z1, z2)!=0 ) continue; - } - obSat |= MASKBIT(i); - } - - if( (pLoop->wsFlags & WHERE_ONEROW)==0 ){ - Index *pPk = 0; - if( (pIndex = pLoop->u.btree.pIndex)==0 - || pIndex->bUnordered - || pIndex->eIndexType==SQLITE4_INDEX_FTS5 - ){ - return 0; - }else{ - isOrderDistinct = pIndex->onError!=OE_None; - pPk = sqlite4FindPrimaryKey(pIndex->pTable, 0); - nColumn = idxColumnCount(pIndex, pPk); - } - - /* Loop through all columns of the index and deal with the ones - ** that are not constrained by == or IN. - */ - rev = revSet = 0; - for(j=0; ju.btree.nEq - && ((i = pLoop->aLTerm[j]->eOperator) & (WO_EQ|WO_ISNULL))!=0 - ){ - if( i & WO_ISNULL ){ - testcase( isOrderDistinct ); - isOrderDistinct = 0; - } - continue; - } - - /* Get the column number in the table (iColumn) and sort order - ** (revIdx) for the j-th column of the index. - */ - if( j=0 - && j>=pLoop->u.btree.nEq - && pIndex->pTable->aCol[iColumn].notNull==0 - ){ - isOrderDistinct = 0; - } - - /* Find the ORDER BY term that corresponds to the j-th column - ** of the index and and mark that ORDER BY term off - */ - bOnce = 1; - isMatch = 0; - for(i=0; bOnce && ia[i].pExpr); - testcase( wctrlFlags & WHERE_GROUPBY ); - testcase( wctrlFlags & WHERE_DISTINCTBY ); - if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0; - if( pOBExpr->op!=TK_COLUMN ) continue; - if( pOBExpr->iTable!=iCur ) continue; - if( pOBExpr->iColumn!=iColumn ) continue; - if( iColumn>=0 ){ - const char *zIdxColl; - pColl = sqlite4ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); - if( !pColl ) pColl = db->pDfltColl; - zIdxColl = idxColumnCollation(pIndex, pPk, j); - if( sqlite4_stricmp(pColl->zName, zIdxColl)!=0 ) continue; - } - isMatch = 1; - break; - } - if( isMatch ){ - obSat |= MASKBIT(i); - if( (pWInfo->wctrlFlags & WHERE_GROUPBY)==0 ){ - /* Make sure the sort order is compatible in an ORDER BY clause. - ** Sort order is irrelevant for a GROUP BY clause. */ - if( revSet ){ - if( (rev ^ revIdx)!=pOrderBy->a[i].sortOrder ) return 0; - }else{ - rev = revIdx ^ pOrderBy->a[i].sortOrder; - if( rev ) *pRevMask |= MASKBIT(iLoop); - revSet = 1; - } - } - }else{ - /* No match found */ - if( j==0 || jmaskSelf; - for(i=0; ia[i].pExpr; - if( (exprTableUsage(&pWInfo->sMaskSet, p)&~orderDistinctMask)==0 ){ - obSat |= MASKBIT(i); - } - } - } - } /* End the loop over all WhereLoops from outer-most down to inner-most */ - if( obSat==obDone ) return 1; - if( !isOrderDistinct ) return 0; - return -1; -} - -#ifdef WHERETRACE_ENABLED -/* For debugging use only: */ -static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){ - static char zName[65]; - int i; - for(i=0; iaLoop[i]->cId; } - if( pLast ) zName[i++] = pLast->cId; - zName[i] = 0; - return zName; -} -#endif - - -/* -** Given the list of WhereLoop objects at pWInfo->pLoops, this routine -** attempts to find the lowest cost path that visits each WhereLoop -** once. This path is then loaded into the pWInfo->a[].pWLoop fields. -** -** Assume that the total number of output rows that will need to be sorted -** will be nRowEst (in the 10*log2 representation). Or, ignore sorting -** costs if nRowEst==0. -** -** Return SQLITE4_OK on success or SQLITE4_NOMEM of a memory allocation -** error occurs. -*/ -static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){ - int mxChoice; /* Maximum number of simultaneous paths tracked */ - int nLoop; /* Number of terms in the join */ - Parse *pParse; /* Parsing context */ - sqlite4 *db; /* The database connection */ - int iLoop; /* Loop counter over the terms of the join */ - int ii, jj; /* Loop counters */ - WhereCost rCost; /* Cost of a path */ - WhereCost mxCost = 0; /* Maximum cost of a set of paths */ - WhereCost rSortCost; /* Cost to do a sort */ - int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */ - WherePath *aFrom; /* All nFrom paths at the previous level */ - WherePath *aTo; /* The nTo best paths at the current level */ - WherePath *pFrom; /* An element of aFrom[] that we are working on */ - WherePath *pTo; /* An element of aTo[] that we are working on */ - WhereLoop *pWLoop; /* One of the WhereLoop objects */ - WhereLoop **pX; /* Used to divy up the pSpace memory */ - char *pSpace; /* Temporary memory used by this routine */ - - pParse = pWInfo->pParse; - db = pParse->db; - nLoop = pWInfo->nLevel; - /* TUNING: For simple queries, only the best path is tracked. - ** For 2-way joins, the 5 best paths are followed. - ** For joins of 3 or more tables, track the 10 best paths */ - mxChoice = (nLoop==1) ? 1 : (nLoop==2 ? 5 : 10); - assert( nLoop<=pWInfo->pTabList->nSrc ); - WHERETRACE(0x002, ("---- begin solver\n")); - - /* Allocate and initialize space for aTo and aFrom */ - ii = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2; - pSpace = sqlite4DbMallocRaw(db, ii); - if( pSpace==0 ) return SQLITE4_NOMEM; - aTo = (WherePath*)pSpace; - aFrom = aTo+mxChoice; - memset(aFrom, 0, sizeof(aFrom[0])); - pX = (WhereLoop**)(aFrom+mxChoice); - for(ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop){ - pFrom->aLoop = pX; - } - - /* Seed the search with a single WherePath containing zero WhereLoops. - ** - ** TUNING: Do not let the number of iterations go above 25. If the cost - ** of computing an automatic index is not paid back within the first 25 - ** rows, then do not use the automatic index. */ - aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==whereCost(25) ); - nFrom = 1; - - /* Precompute the cost of sorting the final result set, if the caller - ** to sqlite4WhereBegin() was concerned about sorting */ - rSortCost = 0; - if( pWInfo->pOrderBy==0 || nRowEst==0 ){ - aFrom[0].isOrderedValid = 1; - }else{ - /* TUNING: Estimated cost of sorting is N*log2(N) where N is the - ** number of output rows. */ - rSortCost = nRowEst + estLog(nRowEst); - WHERETRACE(0x002,("---- sort cost=%-3d\n", rSortCost)); - } - - /* Compute successively longer WherePaths using the previous generation - ** of WherePaths as the basis for the next. Keep track of the mxChoice - ** best paths at each generation */ - for(iLoop=0; iLooppLoops; pWLoop; pWLoop=pWLoop->pNextLoop){ - Bitmask maskNew; - Bitmask revMask = 0; - u8 isOrderedValid = pFrom->isOrderedValid; - u8 isOrdered = pFrom->isOrdered; - if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue; - if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue; - /* At this point, pWLoop is a candidate to be the next loop. - ** Compute its cost */ - rCost = whereCostAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow); - rCost = whereCostAdd(rCost, pFrom->rCost); - maskNew = pFrom->maskLoop | pWLoop->maskSelf; - if( !isOrderedValid ){ - switch( wherePathSatisfiesOrderBy(pWInfo, - pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags, - iLoop, pWLoop, &revMask) ){ - case 1: /* Yes. pFrom+pWLoop does satisfy the ORDER BY clause */ - isOrdered = 1; - isOrderedValid = 1; - break; - case 0: /* No. pFrom+pWLoop will require a separate sort */ - isOrdered = 0; - isOrderedValid = 1; - rCost = whereCostAdd(rCost, rSortCost); - break; - default: /* Cannot tell yet. Try again on the next iteration */ - break; - } - }else{ - revMask = pFrom->revLoop; - } - /* Check to see if pWLoop should be added to the mxChoice best so far */ - for(jj=0, pTo=aTo; jjmaskLoop==maskNew && pTo->isOrderedValid==isOrderedValid ){ - testcase( jj==nTo-1 ); - break; - } - } - if( jj>=nTo ){ - if( nTo>=mxChoice && rCost>=mxCost ){ -#ifdef WHERETRACE_ENABLED - if( sqlite4WhereTrace&0x4 ){ - sqlite4DebugPrintf("Skip %s cost=%3d order=%c\n", - wherePathName(pFrom, iLoop, pWLoop), rCost, - isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?'); - } -#endif - continue; - } - /* Add a new Path to the aTo[] set */ - if( nTo0); } - } - pTo = &aTo[jj]; -#ifdef WHERETRACE_ENABLED - if( sqlite4WhereTrace&0x4 ){ - sqlite4DebugPrintf("New %s cost=%-3d order=%c\n", - wherePathName(pFrom, iLoop, pWLoop), rCost, - isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?'); - } -#endif - }else{ - if( pTo->rCost<=rCost ){ -#ifdef WHERETRACE_ENABLED - if( sqlite4WhereTrace&0x4 ){ - sqlite4DebugPrintf( - "Skip %s cost=%-3d order=%c", - wherePathName(pFrom, iLoop, pWLoop), rCost, - isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?'); - sqlite4DebugPrintf(" vs %s cost=%-3d order=%c\n", - wherePathName(pTo, iLoop+1, 0), pTo->rCost, - pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?'); - } -#endif - testcase( pTo->rCost==rCost ); - continue; - } - testcase( pTo->rCost==rCost+1 ); - /* A new and better score for a previously created equivalent path */ -#ifdef WHERETRACE_ENABLED - if( sqlite4WhereTrace&0x4 ){ - sqlite4DebugPrintf( - "Update %s cost=%-3d order=%c", - wherePathName(pFrom, iLoop, pWLoop), rCost, - isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?'); - sqlite4DebugPrintf(" was %s cost=%-3d order=%c\n", - wherePathName(pTo, iLoop+1, 0), pTo->rCost, - pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?'); - } -#endif - } - /* pWLoop is a winner. Add it to the set of best so far */ - pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf; - pTo->revLoop = revMask; - pTo->nRow = pFrom->nRow + pWLoop->nOut; - pTo->rCost = rCost; - pTo->isOrderedValid = isOrderedValid; - pTo->isOrdered = isOrdered; - memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop); - pTo->aLoop[iLoop] = pWLoop; - if( nTo>=mxChoice ){ - mxCost = aTo[0].rCost; - for(jj=1, pTo=&aTo[1]; jjrCost>mxCost ) mxCost = pTo->rCost; - } - } - } - } - -#ifdef WHERETRACE_ENABLED - if( sqlite4WhereTrace>=2 ){ - sqlite4DebugPrintf("---- after round %d ----\n", iLoop); - for(ii=0, pTo=aTo; iirCost, pTo->nRow, - pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?'); - if( pTo->isOrderedValid && pTo->isOrdered ){ - sqlite4DebugPrintf(" rev=0x%llx\n", pTo->revLoop); - }else{ - sqlite4DebugPrintf("\n"); - } - } - } -#endif - - /* Swap the roles of aFrom and aTo for the next generation */ - pFrom = aTo; - aTo = aFrom; - aFrom = pFrom; - nFrom = nTo; - } - - if( nFrom==0 ){ - sqlite4ErrorMsg(pParse, "no query solution"); - sqlite4DbFree(db, pSpace); - return SQLITE4_ERROR; - } - - /* Find the lowest cost path. pFrom will be left pointing to that path */ - pFrom = aFrom; - assert( nFrom==1 ); -#if 0 /* The following is needed if nFrom is ever more than 1 */ - for(ii=1; iirCost>aFrom[ii].rCost ) pFrom = &aFrom[ii]; - } -#endif - assert( pWInfo->nLevel==nLoop ); - /* Load the lowest cost path into pWInfo */ - for(iLoop=0; iLoopa + iLoop; - pLevel->pWLoop = pWLoop = pFrom->aLoop[iLoop]; - pLevel->iFrom = pWLoop->iTab; - pLevel->iTabCur = pWInfo->pTabList->a[pLevel->iFrom].iCursor; - } - if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)!=0 - && (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0 - && pWInfo->eDistinct==WHERE_DISTINCT_NOOP - && nRowEst - ){ - Bitmask notUsed; - int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom, - WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used); - if( rc==1 ) pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; - } - if( pFrom->isOrdered ){ - if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){ - pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; - }else{ - pWInfo->bOBSat = 1; - pWInfo->revMask = pFrom->revLoop; - } - } - pWInfo->nRowOut = pFrom->nRow; - - /* Free temporary memory and return success */ - sqlite4DbFree(db, pSpace); - return SQLITE4_OK; -} - -/* -** Most queries use only a single table (they are not joins) and have -** simple == constraints against indexed fields. This routine attempts -** to plan those simple cases using much less ceremony than the -** general-purpose query planner, and thereby yield faster sqlite4_prepare() -** times for the common case. -** -** Return non-zero on success, if this query can be handled by this -** no-frills query planner. Return zero if this query needs the -** general-purpose query planner. -*/ -static int whereShortCut(WhereLoopBuilder *pBuilder){ - WhereInfo *pWInfo; - struct SrcListItem *pItem; - WhereClause *pWC; - WhereTerm *pTerm; - WhereLoop *pLoop; - int iCur; - int j; - Table *pTab; - Index *pIdx; - - pWInfo = pBuilder->pWInfo; - if( pWInfo->wctrlFlags & WHERE_FORCE_TABLE ) return 0; - assert( pWInfo->pTabList->nSrc>=1 ); - pItem = pWInfo->pTabList->a; - pTab = pItem->pTab; - if( IsVirtual(pTab) ) return 0; - if( pItem->zIndex ) return 0; - iCur = pItem->iCursor; - pWC = &pWInfo->sWC; - pLoop = pBuilder->pNew; - pLoop->wsFlags = 0; - - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->onError==OE_None ) continue; - for(j=0; jnColumn; j++){ - pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ, pIdx); - if( pTerm==0 ) break; - whereLoopResize(pWInfo->pParse->db, pLoop, j); - pLoop->aLTerm[j] = pTerm; - } - if( j!=pIdx->nColumn ) continue; - pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED; - if( (pItem->colUsed & ~columnsInIndex(pIdx))==0 ){ - pLoop->wsFlags |= WHERE_IDX_ONLY; - } - pLoop->nLTerm = j; - pLoop->u.btree.nEq = j; - pLoop->u.btree.pIndex = pIdx; - /* TUNING: Cost of a unique index lookup is 15 */ - pLoop->rRun = 39; /* 39==whereCost(15) */ - break; - } - - if( pLoop->wsFlags ){ - pLoop->nOut = (WhereCost)1; - pWInfo->a[0].pWLoop = pLoop; - pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur); - pWInfo->a[0].iTabCur = iCur; - pWInfo->nRowOut = 1; - if( pWInfo->pOrderBy ) pWInfo->bOBSat = 1; - if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){ - pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; - } -#ifdef SQLITE4_DEBUG - pLoop->cId = '0'; -#endif - return 1; - } - return 0; -} /* ** Generate the beginning of the loop used for WHERE clause processing. ** The return value is a pointer to an opaque structure that contains ** information needed to terminate the loop. Later, the calling routine @@ -5692,11 +4525,11 @@ ** appear in the FROM clause if a different order is better able to make ** use of indices. Note also that when the IN operator appears in ** the WHERE clause, it might result in additional nested loops for ** scanning through all values on the right-hand side of the IN. ** -** There are Btree cursors associated with each table. t1 uses cursor +** There are cursors associated with each table. t1 uses cursor ** number pTabList->a[0].iCursor. t2 uses the cursor pTabList->a[1].iCursor. ** And so forth. This routine generates code to open those VDBE cursors ** and sqlite4WhereEnd() generates the code to close them. ** ** The code that sqlite4WhereBegin() generates leaves the cursors named @@ -5735,50 +4568,44 @@ ** fi ** end ** ** ORDER BY CLAUSE PROCESSING ** -** pOrderBy is a pointer to the ORDER BY clause (or the GROUP BY clause -** if the WHERE_GROUPBY flag is set in wctrlFlags) of a SELECT statement +** *ppOrderBy is a pointer to the ORDER BY clause of a SELECT statement, ** if there is one. If there is no ORDER BY clause or if this routine -** is called from an UPDATE or DELETE statement, then pOrderBy is NULL. +** is called from an UPDATE or DELETE statement, then ppOrderBy is NULL. +** +** If an index can be used so that the natural output order of the table +** scan is correct for the ORDER BY clause, then that index is used and +** *ppOrderBy is set to NULL. This is an optimization that prevents an +** unnecessary sort of the result set if an index appropriate for the +** ORDER BY clause already exists. +** +** If the where clause loops cannot be arranged to provide the correct +** output order, then the *ppOrderBy is unchanged. */ WhereInfo *sqlite4WhereBegin( Parse *pParse, /* The parser context */ - SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */ + SrcList *pTabList, /* A list of all tables to be scanned */ Expr *pWhere, /* The WHERE clause */ - ExprList *pOrderBy, /* An ORDER BY clause, or NULL */ - ExprList *pResultSet, /* Result set of the query */ - u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */ - int iIdxCur /* If WHERE_ONETABLE_ONLY is set, index cursor number */ + ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */ + ExprList *pDistinct, /* The select-list for DISTINCT queries - or NULL */ + u16 wctrlFlags /* One of the WHERE_* flags defined in sqliteInt.h */ ){ + int i; /* Loop counter */ int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */ int nTabList; /* Number of elements in pTabList */ WhereInfo *pWInfo; /* Will become the return value of this function */ Vdbe *v = pParse->pVdbe; /* The virtual database engine */ Bitmask notReady; /* Cursors that are not yet positioned */ - WhereLoopBuilder sWLB; /* The WhereLoop builder */ WhereMaskSet *pMaskSet; /* The expression mask set */ - WhereLevel *pLevel; /* A single level in pWInfo->a[] */ - WhereLoop *pLoop; /* Pointer to a single WhereLoop object */ - int ii; /* Loop counter */ + WhereClause *pWC; /* Decomposition of the WHERE clause */ + SrcListItem *pTabItem; /* A single entry from pTabList */ + WhereLevel *pLevel; /* A single level in the pWInfo list */ + int iFrom; /* First unused FROM clause element */ + int andFlags; /* AND-ed combination of all pWC->a[].wtFlags */ sqlite4 *db; /* Database connection */ - int rc; /* Return code */ - - /* src4: In SQLite3, the caller would set this flag. */ - if( pResultSet ) wctrlFlags |= WHERE_WANT_DISTINCT; - - /* Variable initialization */ - db = pParse->db; - memset(&sWLB, 0, sizeof(sWLB)); - sWLB.pOrderBy = pOrderBy; - - /* Disable the DISTINCT optimization if SQLITE4_DistinctOpt is set via - ** sqlite4_test_ctrl(SQLITE4_TESTCTRL_OPTIMIZATIONS,...) */ - if( OptimizationDisabled(db, SQLITE4_DistinctOpt) ){ - wctrlFlags &= ~WHERE_WANT_DISTINCT; - } /* The number of tables in the FROM clause is limited by the number of ** bits in a Bitmask */ testcase( pTabList->nSrc==BMS ); @@ -5799,61 +4626,51 @@ ** struct, the contents of WhereInfo.a[], the WhereClause structure ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte ** field (type Bitmask) it must be aligned on an 8-byte boundary on ** some architectures. Hence the ROUND8() below. */ + db = pParse->db; nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel)); - pWInfo = sqlite4DbMallocZero(db, nByteWInfo + sizeof(WhereLoop)); + pWInfo = sqlite4DbMallocZero(db, + nByteWInfo + + sizeof(WhereClause) + + sizeof(WhereMaskSet) + ); if( db->mallocFailed ){ sqlite4DbFree(db, pWInfo); pWInfo = 0; goto whereBeginError; } pWInfo->nLevel = nTabList; pWInfo->pParse = pParse; pWInfo->pTabList = pTabList; - pWInfo->pOrderBy = pOrderBy; - pWInfo->pResultSet = pResultSet; pWInfo->iBreak = sqlite4VdbeMakeLabel(v); + pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo]; pWInfo->wctrlFlags = wctrlFlags; pWInfo->savedNQueryLoop = pParse->nQueryLoop; - pMaskSet = &pWInfo->sMaskSet; - sWLB.pWInfo = pWInfo; - sWLB.pWC = &pWInfo->sWC; - sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo); - assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) ); - whereLoopInit(sWLB.pNew); -#ifdef SQLITE4_DEBUG - sWLB.pNew->cId = '*'; -#endif + pMaskSet = (WhereMaskSet*)&pWC[1]; + + /* Disable the DISTINCT optimization if SQLITE4_DistinctOpt is set via + ** sqlite4_test_ctrl(SQLITE4_TESTCTRL_OPTIMIZATIONS,...) */ + if( db->flags & SQLITE4_DistinctOpt ) pDistinct = 0; /* Split the WHERE clause into separate subexpressions where each ** subexpression is separated by an AND operator. */ initMaskSet(pMaskSet); - whereClauseInit(&pWInfo->sWC, pWInfo); + whereClauseInit(pWC, pParse, pMaskSet, wctrlFlags); sqlite4ExprCodeConstants(pParse, pWhere); - whereSplit(&pWInfo->sWC, pWhere, TK_AND); /* IMP: R-15842-53296 */ - sqlite4CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */ + whereSplit(pWC, pWhere, TK_AND); /* IMP: R-15842-53296 */ /* Special case: a WHERE clause that is constant. Evaluate the ** expression and either jump over all of the code or fall thru. */ if( pWhere && (nTabList==0 || sqlite4ExprIsConstantNotJoin(pWhere)) ){ sqlite4ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE4_JUMPIFNULL); pWhere = 0; } - /* Special case: No FROM clause - */ - if( nTabList==0 ){ - if( pOrderBy ) pWInfo->bOBSat = 1; - if( wctrlFlags & WHERE_WANT_DISTINCT ){ - pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; - } - } - /* Assign a bit from the bitmask to every term in the FROM clause. ** ** When assigning bitmask values to FROM clause cursors, it must be ** the case that if X is the bitmask for the N-th FROM clause term then ** the bitmask for all FROM clause terms to the left of the N-th term @@ -5860,246 +4677,408 @@ ** is (X-1). An expression from the ON clause of a LEFT JOIN can use ** its Expr.iRightJoinTable value to find the bitmask of the right table ** of the join. Subtracting one from the right table bitmask gives a ** bitmask for all tables to the left of the join. Knowing the bitmask ** for all tables to the left of a left join is important. Ticket #3015. + ** + ** Configure the WhereClause.vmask variable so that bits that correspond + ** to virtual table cursors are set. This is used to selectively disable + ** the OR-to-IN transformation in exprAnalyzeOrTerm(). It is not helpful + ** with virtual tables. ** ** Note that bitmasks are created for all pTabList->nSrc tables in ** pTabList, not just the first nTabList tables. nTabList is normally ** equal to pTabList->nSrc but might be shortened to 1 if the ** WHERE_ONETABLE_ONLY flag is set. */ - for(ii=0; iinSrc; ii++){ - createMask(pMaskSet, pTabList->a[ii].iCursor); + assert( pWC->vmask==0 && pMaskSet->n==0 ); + for(i=0; inSrc; i++){ + createMask(pMaskSet, pTabList->a[i].iCursor); +#ifndef SQLITE4_OMIT_VIRTUALTABLE + if( ALWAYS(pTabList->a[i].pTab) && IsVirtual(pTabList->a[i].pTab) ){ + pWC->vmask |= ((Bitmask)1 << i); + } +#endif } #ifndef NDEBUG { Bitmask toTheLeft = 0; - for(ii=0; iinSrc; ii++){ - Bitmask m = getMask(pMaskSet, pTabList->a[ii].iCursor); + for(i=0; inSrc; i++){ + Bitmask m = getMask(pMaskSet, pTabList->a[i].iCursor); assert( (m-1)==toTheLeft ); toTheLeft |= m; } } #endif - /* Analyze all of the subexpressions. Note that exprAnalyze() might - ** add new virtual terms onto the end of the WHERE clause. We do not - ** want to analyze these virtual terms, so start analyzing at the end - ** and work forward so that the added virtual terms are never processed. - */ - exprAnalyzeAll(pTabList, &pWInfo->sWC); + /* Analyze all of the subexpressions. */ + exprAnalyzeAll(pTabList, pWC); if( db->mallocFailed ){ goto whereBeginError; } - /* If the ORDER BY (or GROUP BY) clause contains references to general - ** expressions, then we won't be able to satisfy it using indices, so - ** go ahead and disable it now. - */ - if( pOrderBy && (wctrlFlags & WHERE_WANT_DISTINCT)!=0 ){ - for(ii=0; iinExpr; ii++){ - Expr *pExpr = sqlite4ExprSkipCollate(pOrderBy->a[ii].pExpr); - if( pExpr->op!=TK_COLUMN ){ - pWInfo->pOrderBy = pOrderBy = 0; - break; - }else if( pExpr->iColumn<0 ){ - break; - } - } - } - - if( wctrlFlags & WHERE_WANT_DISTINCT ){ - if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ - /* The DISTINCT marking is pointless. Ignore it. */ - pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; - }else if( pOrderBy==0 ){ - /* Try to ORDER BY the result set to make distinct processing easier */ - pWInfo->wctrlFlags |= WHERE_DISTINCTBY; - pWInfo->pOrderBy = pResultSet; - } - } - - /* Construct the WhereLoop objects */ - WHERETRACE(0xffff,("*** Optimizer Start ***\n")); - if( nTabList!=1 || whereShortCut(&sWLB)==0 ){ - rc = whereLoopAddAll(&sWLB); - if( rc ) goto whereBeginError; - - /* Display all of the WhereLoop objects if wheretrace is enabled */ -#ifdef WHERETRACE_ENABLED - if( sqlite4WhereTrace ){ - WhereLoop *p; - int i; - static char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz" - "ABCDEFGHIJKLMNOPQRSTUVWYXZ"; - for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){ - p->cId = zLabel[i%sizeof(zLabel)]; - whereLoopPrint(p, pTabList); - } - } -#endif - - wherePathSolver(pWInfo, 0); - if( db->mallocFailed ) goto whereBeginError; - if( pWInfo->pOrderBy ){ - wherePathSolver(pWInfo, pWInfo->nRowOut+1); - if( db->mallocFailed ) goto whereBeginError; - } - } - if( pWInfo->pOrderBy==0 && (db->flags & SQLITE4_ReverseOrder)!=0 ){ - pWInfo->revMask = (Bitmask)(-1); - } - if( pParse->nErr || NEVER(db->mallocFailed) ){ + /* Check if the DISTINCT qualifier, if there is one, is redundant. + ** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to + ** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT. + */ + if( pDistinct && isDistinctRedundant(pParse, pTabList, pWC, pDistinct) ){ + pDistinct = 0; + pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; + } + + /* Chose the best index to use for each table in the FROM clause. + ** + ** This loop fills in the following fields: + ** + ** pWInfo->a[].pIdx The index to use for this level of the loop. + ** pWInfo->a[].wsFlags WHERE_xxx flags associated with pIdx + ** pWInfo->a[].nEq The number of == and IN constraints + ** pWInfo->a[].iFrom Which term of the FROM clause is being coded + ** pWInfo->a[].iTabCur The VDBE cursor for the database table + ** pWInfo->a[].iIdxCur The VDBE cursor for the index + ** pWInfo->a[].pTerm When wsFlags==WO_OR, the OR-clause term + ** + ** This loop also figures out the nesting order of tables in the FROM + ** clause. + */ + notReady = ~(Bitmask)0; + andFlags = ~0; + WHERETRACE(("*** Optimizer Start ***\n")); + for(i=iFrom=0, pLevel=pWInfo->a; i=0 && bestJ<0; isOptimal--){ + Bitmask mask; /* Mask of tables not yet ready */ + for(j=iFrom, pTabItem=&pTabList->a[j]; jjointype & (JT_LEFT|JT_CROSS))!=0; + if( j!=iFrom && doNotReorder ) break; + m = getMask(pMaskSet, pTabItem->iCursor); + if( (m & notReady)==0 ){ + if( j==iFrom ) iFrom++; + continue; + } + mask = (isOptimal ? m : notReady); + pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0); + pDist = (i==0 ? pDistinct : 0); + if( pTabItem->pIndex==0 ) nUnconstrained++; + + WHERETRACE(("=== trying table %d with isOptimal=%d ===\n", + j, isOptimal)); + assert( pTabItem->pTab ); + + if( bestMatchIdx(pParse, pWC, pTabItem, notReady, &sCost) ){ + /* no-op */ + }else +#ifndef SQLITE4_OMIT_VIRTUALTABLE + if( IsVirtual(pTabItem->pTab) ){ + sqlite4_index_info **pp = &pWInfo->a[j].pIdxInfo; + bestVirtualIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy, + &sCost, pp); + }else +#endif + { + bestKVIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy, + pDist, &sCost); + } + + assert( isOptimal || (sCost.used¬Ready)==0 ); + + /* If an INDEXED BY clause is present, then the plan must use that + ** index if it uses any index at all */ + assert( pTabItem->pIndex==0 + || (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 + || sCost.plan.u.pIdx==pTabItem->pIndex ); + + if( isOptimal && (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){ + notIndexed |= m; + } + + /* Conditions under which this table becomes the best so far: + ** + ** (1) The table must not depend on other tables that have not + ** yet run. + ** + ** (2) A full-table-scan plan cannot supercede indexed plan unless + ** the full-table-scan is an "optimal" plan as defined above. + ** + ** (3) All tables have an INDEXED BY clause or this table lacks an + ** INDEXED BY clause or this table uses the specific + ** index specified by its INDEXED BY clause. This rule ensures + ** that a best-so-far is always selected even if an impossible + ** combination of INDEXED BY clauses are given. The error + ** will be detected and relayed back to the application later. + ** The NEVER() comes about because rule (2) above prevents + ** An indexable full-table-scan from reaching rule (3). + ** + ** (4) The plan cost must be lower than prior plans or else the + ** cost must be the same and the number of rows must be lower. + */ + if( (sCost.used¬Ready)==0 /* (1) */ + && (bestJ<0 || (notIndexed&m)!=0 /* (2) */ + || (bestPlan.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 + || (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0) + && (nUnconstrained==0 || pTabItem->pIndex==0 /* (3) */ + || NEVER((sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)) + && (bestJ<0 || sCost.rCost=0 ); + assert( notReady & getMask(pMaskSet, pTabList->a[bestJ].iCursor) ); + WHERETRACE(("*** Optimizer selects table %d for loop %d" + " with cost=%g and nRow=%g\n", + bestJ, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow)); + /* The ALWAYS() that follows was added to hush up clang scan-build */ + if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 && ALWAYS(ppOrderBy) ){ + *ppOrderBy = 0; + } + if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){ + assert( pWInfo->eDistinct==0 ); + pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; + } + andFlags &= bestPlan.plan.wsFlags; + pLevel->plan = bestPlan.plan; + testcase( bestPlan.plan.wsFlags & WHERE_INDEXED ); + testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX ); + if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){ + pLevel->iIdxCur = pParse->nTab++; + }else{ + pLevel->iIdxCur = -1; + } + notReady &= ~getMask(pMaskSet, pTabList->a[bestJ].iCursor); + pLevel->iFrom = (u8)bestJ; + if( bestPlan.plan.nRow>=(double)1 ){ + pParse->nQueryLoop *= bestPlan.plan.nRow; + } + + /* Check that if the table scanned by this loop iteration had an + ** INDEXED BY clause attached to it, that the named index is being + ** used for the scan. If not, then query compilation has failed. + ** Return an error. + */ + pIdx = pTabList->a[bestJ].pIndex; + if( pIdx ){ + if( (bestPlan.plan.wsFlags & WHERE_INDEXED)==0 ){ + sqlite4ErrorMsg(pParse, "cannot use index: %s", pIdx->zName); + goto whereBeginError; + }else{ + /* If an INDEXED BY clause is used, the bestIndex() function is + ** guaranteed to find the index specified in the INDEXED BY clause + ** if it find an index at all. */ + assert( bestPlan.plan.u.pIdx==pIdx ); + } + } + } + WHERETRACE(("*** Optimizer Finished ***\n")); + if( pParse->nErr || db->mallocFailed ){ goto whereBeginError; } -#ifdef WHERETRACE_ENABLED - if( sqlite4WhereTrace ){ - int ii; - sqlite4DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut); - if( pWInfo->bOBSat ){ - sqlite4DebugPrintf(" ORDERBY=0x%llx", pWInfo->revMask); - } - switch( pWInfo->eDistinct ){ - case WHERE_DISTINCT_UNIQUE: { - sqlite4DebugPrintf(" DISTINCT=unique"); - break; - } - case WHERE_DISTINCT_ORDERED: { - sqlite4DebugPrintf(" DISTINCT=ordered"); - break; - } - case WHERE_DISTINCT_UNORDERED: { - sqlite4DebugPrintf(" DISTINCT=unordered"); - break; - } - } - sqlite4DebugPrintf("\n"); - for(ii=0; iinLevel; ii++){ - whereLoopPrint(pWInfo->a[ii].pWLoop, pTabList); - } - } -#endif - /* Attempt to omit tables from the join that do not effect the result */ - if( pWInfo->nLevel>=2 - && pResultSet!=0 - && OptimizationEnabled(db, SQLITE4_OmitNoopJoin) - ){ - Bitmask tabUsed = exprListTableUsage(pMaskSet, pResultSet); - if( pOrderBy ) tabUsed |= exprListTableUsage(pMaskSet, pOrderBy); - while( pWInfo->nLevel>=2 ){ - WhereTerm *pTerm, *pEnd; - pLoop = pWInfo->a[pWInfo->nLevel-1].pWLoop; - if( (pWInfo->pTabList->a[pLoop->iTab].jointype & JT_LEFT)==0 ) break; - if( (wctrlFlags & WHERE_WANT_DISTINCT)==0 - && (pLoop->wsFlags & WHERE_ONEROW)==0 - ){ - break; - } - if( (tabUsed & pLoop->maskSelf)!=0 ) break; - pEnd = sWLB.pWC->a + sWLB.pWC->nTerm; - for(pTerm=sWLB.pWC->a; pTermprereqAll & pLoop->maskSelf)!=0 - && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) - ){ - break; - } - } - if( pTerm drop loop %c not used\n", pLoop->cId)); - pWInfo->nLevel--; - nTabList--; - } - } - WHERETRACE(0xffff,("*** Optimizer Finished ***\n")); - pWInfo->pParse->nQueryLoop += pWInfo->nRowOut; + + /* If the total query only selects a single row, then the ORDER BY + ** clause is irrelevant. + */ + if( (andFlags & WHERE_UNIQUE)!=0 && ppOrderBy ){ + *ppOrderBy = 0; + } /* If the caller is an UPDATE or DELETE statement that is requesting ** to use a one-pass algorithm, determine if this is appropriate. ** The one-pass algorithm only works if the WHERE clause constraints ** the statement to update a single row. */ assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); - if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 - && (pWInfo->a[0].pWLoop->wsFlags & WHERE_ONEROW)!=0 ){ + if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 && (andFlags & WHERE_UNIQUE)!=0 ){ pWInfo->okOnePass = 1; - pWInfo->a[0].pWLoop->wsFlags &= ~WHERE_IDX_ONLY; + pWInfo->a[0].plan.wsFlags &= ~WHERE_IDX_ONLY; } /* Open all tables in the pTabList and any indices selected for ** searching those tables. */ + sqlite4CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */ notReady = ~(Bitmask)0; - for(ii=0, pLevel=pWInfo->a; iinRowOut = (double)1; + for(i=0, pLevel=pWInfo->a; ia[pLevel->iFrom]; pTab = pTabItem->pTab; + pLevel->iTabCur = pTabItem->iCursor; + pWInfo->nRowOut *= pLevel->plan.nRow; iDb = sqlite4SchemaToIndex(db, pTab->pSchema); - pLoop = pLevel->pWLoop; if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){ /* Do nothing */ }else #ifndef SQLITE4_OMIT_VIRTUALTABLE - if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){ + if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ const char *pVTab = (const char *)sqlite4GetVTable(db, pTab); int iCur = pTabItem->iCursor; sqlite4VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB); - }else if( IsVirtual(pTab) ){ - /* noop */ }else #endif - if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 + if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0 && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){ int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead; sqlite4OpenPrimaryKey(pParse, pTabItem->iCursor, iDb, pTab, op); - testcase( !pWInfo->okOnePass && pTab->nCol==BMS-1 ); - testcase( !pWInfo->okOnePass && pTab->nCol==BMS ); + testcase( pTab->nCol==BMS-1 ); + testcase( pTab->nCol==BMS ); } #ifndef SQLITE4_OMIT_AUTOMATIC_INDEX - if( (pLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){ - constructAutomaticIndex(pParse, &pWInfo->sWC, pTabItem, notReady, pLevel); + if( (pLevel->plan.wsFlags & WHERE_TEMP_INDEX)!=0 ){ + constructAutomaticIndex(pParse, pWC, pTabItem, notReady, pLevel); }else #endif - if( pLoop->wsFlags & WHERE_INDEXED ){ - Index *pIx = pLoop->u.btree.pIndex; + if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){ + Index *pIx = pLevel->plan.u.pIdx; if( pIx->eIndexType==SQLITE4_INDEX_PRIMARYKEY ){ pLevel->iIdxCur = pTabItem->iCursor; - }else{ - /* FIXME: As an optimization use pTabItem->iCursor if WHERE_IDX_ONLY */ - pLevel->iIdxCur = iIdxCur ? iIdxCur : pParse->nTab++; - if( pIx->eIndexType!=SQLITE4_INDEX_FTS5 ){ - KeyInfo *pKey = sqlite4IndexKeyinfo(pParse, pIx); - assert( pIx->pSchema==pTab->pSchema ); - assert( pLevel->iIdxCur>=0 ); - sqlite4VdbeAddOp4(v, OP_OpenRead, pLevel->iIdxCur, pIx->tnum, iDb, - (char*)pKey, P4_KEYINFO_HANDOFF); - VdbeComment((v, "%s", pIx->zName)); - } + }else if( pIx->eIndexType!=SQLITE4_INDEX_FTS5 ){ + KeyInfo *pKey = sqlite4IndexKeyinfo(pParse, pIx); + int iIdxCur = pLevel->iIdxCur; + assert( pIx->pSchema==pTab->pSchema ); + assert( iIdxCur>=0 ); + sqlite4VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIx->tnum, iDb, + (char*)pKey, P4_KEYINFO_HANDOFF); + VdbeComment((v, "%s", pIx->zName)); } } sqlite4CodeVerifySchema(pParse, iDb); - notReady &= ~getMask(&pWInfo->sMaskSet, pTabItem->iCursor); + notReady &= ~getMask(pWC->pMaskSet, pTabItem->iCursor); } pWInfo->iTop = sqlite4VdbeCurrentAddr(v); if( db->mallocFailed ) goto whereBeginError; /* Generate the code to do the search. Each iteration of the for ** loop below generates code for a single nested loop of the VM ** program. */ notReady = ~(Bitmask)0; - for(ii=0; iia[ii]; - explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags); - notReady = codeOneLoopStart(pWInfo, ii, notReady); + for(i=0; ia[i]; + explainOneScan(pParse, pTabList, pLevel, i, pLevel->iFrom, wctrlFlags); + notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady, pWhere); pWInfo->iContinue = pLevel->addrCont; } - /* Done. */ +#ifdef SQLITE4_TEST /* For testing and debugging use only */ + /* Record in the query plan information about the current table + ** and the index used to access it (if any). If the table itself + ** is not used, its name is just '{}'. If no index is used + ** the index is listed as "{}". If the primary key is used the + ** index name is '*'. + */ + for(i=0; ia[i]; + pTabItem = &pTabList->a[pLevel->iFrom]; + z = pTabItem->zAlias; + if( z==0 ) z = pTabItem->pTab->zName; + n = sqlite4Strlen30(z); + if( n+nQPlan < sizeof(sqlite4_query_plan)-10 ){ + if( pLevel->plan.wsFlags & WHERE_IDX_ONLY ){ + memcpy(&sqlite4_query_plan[nQPlan], "{}", 2); + nQPlan += 2; + }else{ + memcpy(&sqlite4_query_plan[nQPlan], z, n); + nQPlan += n; + } + sqlite4_query_plan[nQPlan++] = ' '; + } + if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){ + n = sqlite4Strlen30(pLevel->plan.u.pIdx->zName); + if( n+nQPlan < sizeof(sqlite4_query_plan)-2 ){ + memcpy(&sqlite4_query_plan[nQPlan], pLevel->plan.u.pIdx->zName, n); + nQPlan += n; + sqlite4_query_plan[nQPlan++] = ' '; + } + }else{ + memcpy(&sqlite4_query_plan[nQPlan], "{} ", 3); + nQPlan += 3; + } + } + while( nQPlan>0 && sqlite4_query_plan[nQPlan-1]==' ' ){ + sqlite4_query_plan[--nQPlan] = 0; + } + sqlite4_query_plan[nQPlan] = 0; + nQPlan = 0; +#endif /* SQLITE4_TEST // Testing and debugging use only */ + + /* Record the continuation address in the WhereInfo structure. Then + ** clean up and return. + */ return pWInfo; /* Jump here if malloc fails */ whereBeginError: if( pWInfo ){ @@ -6116,46 +5095,44 @@ void sqlite4WhereEnd(WhereInfo *pWInfo){ Parse *pParse = pWInfo->pParse; Vdbe *v = pParse->pVdbe; int i; WhereLevel *pLevel; - WhereLoop *pLoop; SrcList *pTabList = pWInfo->pTabList; sqlite4 *db = pParse->db; /* Generate loop termination code. */ sqlite4ExprCacheClear(pParse); for(i=pWInfo->nLevel-1; i>=0; i--){ pLevel = &pWInfo->a[i]; - pLoop = pLevel->pWLoop; sqlite4VdbeResolveLabel(v, pLevel->addrCont); if( pLevel->op!=OP_Noop ){ sqlite4VdbeAddOp2(v, pLevel->op, pLevel->p1, pLevel->p2); sqlite4VdbeChangeP5(v, pLevel->p5); } - if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){ + if( pLevel->plan.wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){ struct InLoop *pIn; int j; sqlite4VdbeResolveLabel(v, pLevel->addrNxt); for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){ sqlite4VdbeJumpHere(v, pIn->addrInTop+1); - sqlite4VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop); + sqlite4VdbeAddOp2(v, OP_Next, pIn->iCur, pIn->addrInTop); sqlite4VdbeJumpHere(v, pIn->addrInTop-1); } sqlite4DbFree(db, pLevel->u.in.aInLoop); } sqlite4VdbeResolveLabel(v, pLevel->addrBrk); if( pLevel->iLeftJoin ){ int addr; addr = sqlite4VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); - assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 - || (pLoop->wsFlags & WHERE_INDEXED)!=0 ); - if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){ + assert( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0 + || (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ); + if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0 ){ sqlite4VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor); } - if( pLoop->wsFlags & WHERE_INDEXED ){ + if( pLevel->iIdxCur>=0 ){ sqlite4VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); } if( pLevel->op==OP_Return ){ sqlite4VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst); }else{ @@ -6170,80 +5147,62 @@ */ sqlite4VdbeResolveLabel(v, pWInfo->iBreak); /* Close all of the cursors that were opened by sqlite4WhereBegin. */ - assert( pWInfo->nLevel<=pTabList->nSrc ); + assert( pWInfo->nLevel==1 || pWInfo->nLevel==pTabList->nSrc ); for(i=0, pLevel=pWInfo->a; inLevel; i++, pLevel++){ - Index *pIdx = 0; - struct SrcListItem *pTabItem = &pTabList->a[pLevel->iFrom]; + SrcListItem *pTabItem = &pTabList->a[pLevel->iFrom]; Table *pTab = pTabItem->pTab; assert( pTab!=0 ); - pLoop = pLevel->pWLoop; if( (pTab->tabFlags & TF_Ephemeral)==0 && pTab->pSelect==0 && (pWInfo->wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){ - int ws = pLoop->wsFlags; + int ws = pLevel->plan.wsFlags; if( !pWInfo->okOnePass && (ws & WHERE_IDX_ONLY)==0 ){ sqlite4VdbeAddOp1(v, OP_Close, pTabItem->iCursor); } - if( (ws & WHERE_INDEXED)!=0 && (ws & WHERE_AUTO_INDEX)==0 ){ + if( (ws & WHERE_INDEXED)!=0 && (ws & WHERE_TEMP_INDEX)==0 ){ if( pLevel->iIdxCur!=pTabItem->iCursor ){ sqlite4VdbeAddOp1(v, OP_Close, pLevel->iIdxCur); } } } - /* If this scan uses an index, make VDBE code substitutions to read data - ** from the index instead of from the table where possible. In some cases - ** this optimization prevents the table from ever being read, which can - ** yield a significant performance boost. + /* If this scan uses an index, make code substitutions to read data + ** from the index in preference to the table. Sometimes, this means + ** the table need never be read from. This is a performance boost, + ** as the vdbe level waits until the table is read before actually + ** seeking the table cursor to the record corresponding to the current + ** position in the index. ** ** Calls to the code generator in between sqlite4WhereBegin and ** sqlite4WhereEnd will have created code that references the table ** directly. This loop scans all that code looking for opcodes ** that reference the table and converts them into opcodes that ** reference the index. */ - if( pLoop->wsFlags & (WHERE_INDEXED|WHERE_IDX_ONLY) ){ - pIdx = pLoop->u.btree.pIndex; - }else if( pLoop->wsFlags & WHERE_MULTI_OR ){ - pIdx = pLevel->u.pCovidx; - } - if( pIdx && pIdx->eIndexType!=SQLITE4_INDEX_PRIMARYKEY - && !db->mallocFailed - ){ - int *aiCover = pIdx->aiCover; - int nCover = pIdx->nCover; - int k, j, last; - VdbeOp *pOp; - - pOp = sqlite4VdbeGetOp(v, pWInfo->iTop); - last = sqlite4VdbeCurrentAddr(v); - for(k=pWInfo->iTop; kp1!=pLevel->iTabCur ) continue; - if( pOp->opcode==OP_Column ){ - for(j=0; jp2==aiCover[j] ){ - pOp->p2 = j; - pOp->p1 = pLevel->iIdxCur; - break; - } - } - assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || jopcode==OP_RowKey ){ - Index *pPk = sqlite4FindPrimaryKey(pTab, 0); - pOp->p3 = pPk->tnum; - pOp->p1 = pLevel->iIdxCur; - pOp->opcode = OP_IdxRowkey; - } - } - } - - if( (pLoop->wsFlags & WHERE_INDEXED) - && (pLoop->u.btree.pIndex->eIndexType==SQLITE4_INDEX_FTS5) + if( (pLevel->plan.wsFlags & WHERE_TEMP_INDEX) && !db->mallocFailed ){ + VdbeOp *pOp; + VdbeOp *pEnd; + + assert( pLevel->plan.u.pIdx ); + assert( pLevel->iTabCur!=pLevel->iIdxCur ); + pOp = sqlite4VdbeGetOp(v, pWInfo->iTop); + pEnd = &pOp[sqlite4VdbeCurrentAddr(v) - pWInfo->iTop]; + + while( pOpp1==pLevel->iTabCur && pOp->opcode==OP_Column ){ + pOp->p1 = pLevel->iIdxCur; + } + pOp++; + } + } + + if( (pLevel->plan.wsFlags & WHERE_INDEXED) + && (pLevel->plan.u.pIdx->eIndexType==SQLITE4_INDEX_FTS5) ){ VdbeOp *pOp; VdbeOp *pEnd; assert( pLevel->iTabCur!=pLevel->iIdxCur ); Index: test/alter.test ================================================================== --- test/alter.test +++ test/alter.test @@ -88,14 +88,15 @@ table t1 t1 \ index t1i1 t1 \ index t1i2 t1 \ table t1'x1 t1'x1 \ index i3 t1'x1 \ - index {sqlite_t1'x1_unique1} t1'x1 \ + index {sqlite_autoindex_t1'x1_1} t1'x1 \ + index {sqlite_autoindex_t1'x1_2} t1'x1 \ table {temp table} {temp table} \ index i2 {temp table} \ - index {sqlite_temp table_unique1} {temp table} \ + index {sqlite_autoindex_temp table_1} {temp table} \ ] # Make some changes # integrity_check alter-1.3.0 @@ -131,14 +132,15 @@ table -t1- -t1- \ index t1i1 -t1- \ index t1i2 -t1- \ table T2 T2 \ index i3 T2 \ - index {sqlite_T2_unique1} T2 \ + index {sqlite_autoindex_T2_1} T2 \ + index {sqlite_autoindex_T2_2} T2 \ table {TempTab} {TempTab} \ index i2 {TempTab} \ - index {sqlite_TempTab_unique1} {TempTab} \ + index {sqlite_autoindex_TempTab_1} {TempTab} \ ] # Make sure the changes persist after restarting the database. # (The TEMP table will not persist, of course.) # @@ -160,11 +162,12 @@ table -t1- -t1- \ index t1i1 -t1- \ index t1i2 -t1- \ table T2 T2 \ index i3 T2 \ - index {sqlite_T2_unique1} T2 \ + index {sqlite_autoindex_T2_1} T2 \ + index {sqlite_autoindex_T2_2} T2 \ ] } else { execsql { DROP TABLE TempTab; } @@ -208,11 +211,12 @@ table *t1* *t1* \ index t1i1 *t1* \ index t1i2 *t1* \ table \ index i3 \ - index {sqlite__unique1} \ + index {sqlite_autoindex__1} \ + index {sqlite_autoindex__2} \ ] # Check that ALTER TABLE works on attached databases. # ifcapable attach { @@ -589,13 +593,13 @@ } {7} do_test alter-6.2 { execsql " CREATE TABLE ${tbl_name}(a, b, c); " - set ::oid [execsql {SELECT max(rowid) FROM sqlite_master}] + set ::oid [execsql {SELECT max(oid) FROM sqlite_master}] execsql " - SELECT sql FROM sqlite_master WHERE rowid = $::oid; + SELECT sql FROM sqlite_master WHERE oid = $::oid; " } "{CREATE TABLE ${::tbl_name}(a, b, c)}" execsql " SELECT * FROM ${::tbl_name} " @@ -603,28 +607,28 @@ do_test alter-6.3 { execsql " ALTER TABLE $::tbl_name RENAME TO $::tbl_name2 " execsql " - SELECT sql FROM sqlite_master WHERE rowid = $::oid + SELECT sql FROM sqlite_master WHERE oid = $::oid " } "{CREATE TABLE \"${::tbl_name2}\"(a, b, c)}" do_test alter-6.4 { execsql " ALTER TABLE $::tbl_name2 RENAME TO $::tbl_name " execsql " - SELECT sql FROM sqlite_master WHERE rowid = $::oid + SELECT sql FROM sqlite_master WHERE oid = $::oid " } "{CREATE TABLE \"${::tbl_name}\"(a, b, c)}" set ::col_name ghi\1234\jkl do_test alter-6.5 { execsql " ALTER TABLE $::tbl_name ADD COLUMN $::col_name VARCHAR " execsql " - SELECT sql FROM sqlite_master WHERE rowid = $::oid + SELECT sql FROM sqlite_master WHERE oid = $::oid " } "{CREATE TABLE \"${::tbl_name}\"(a, b, c, $::col_name VARCHAR)}" set ::col_name2 B\3421\A do_test alter-6.6 { db close @@ -631,11 +635,11 @@ sqlite4 db test.db execsql " ALTER TABLE $::tbl_name ADD COLUMN $::col_name2 " execsql " - SELECT sql FROM sqlite_master WHERE rowid = $::oid + SELECT sql FROM sqlite_master WHERE oid = $::oid " } "{CREATE TABLE \"${::tbl_name}\"(a, b, c, $::col_name VARCHAR, $::col_name2)}" do_test alter-6.7 { execsql " INSERT INTO ${::tbl_name} VALUES(1, 2, 3, 4, 5); @@ -679,18 +683,18 @@ # alter-9.X - Special test: Make sure the sqlite_rename_trigger() and # rename_table() functions do not crash when handed bad input. # ifcapable trigger { do_test alter-9.1 { - execsql {SELECT SQLITE_RENAME_TRIGGER(0,0)} + execsql {SELECT SQLITE4_RENAME_TRIGGER(0,0)} } {{}} } do_test alter-9.2 { execsql { - SELECT SQLITE_RENAME_TABLE(0,0); - SELECT SQLITE_RENAME_TABLE(10,20); - SELECT SQLITE_RENAME_TABLE('foo', 'foo'); + SELECT SQLITE4_RENAME_TABLE(0,0); + SELECT SQLITE4_RENAME_TABLE(10,20); + SELECT SQLITE4_RENAME_TABLE('foo', 'foo'); } } {{} {} {}} #------------------------------------------------------------------------ # alter-10.X - Make sure ALTER TABLE works with multi-byte UTF-8 characters @@ -700,19 +704,19 @@ execsql "CREATE TABLE xyz(x UNIQUE)" execsql "ALTER TABLE xyz RENAME TO xyz\u1234abc" execsql {SELECT name FROM sqlite_master WHERE name GLOB 'xyz*'} } [list xyz\u1234abc] do_test alter-10.2 { - execsql {SELECT name FROM sqlite_master WHERE name GLOB 'sqlite_*unique*'} -} [list sqlite_xyz\u1234abc_unique1] + execsql {SELECT name FROM sqlite_master WHERE name GLOB 'sqlite_autoindex*'} +} [list sqlite_autoindex_xyz\u1234abc_1] do_test alter-10.3 { execsql "ALTER TABLE xyz\u1234abc RENAME TO xyzabc" execsql {SELECT name FROM sqlite_master WHERE name GLOB 'xyz*'} } [list xyzabc] do_test alter-10.4 { - execsql {SELECT name FROM sqlite_master WHERE name GLOB 'sqlite_*unique*'} -} [list sqlite_xyzabc_unique1] + execsql {SELECT name FROM sqlite_master WHERE name GLOB 'sqlite_autoindex*'} +} [list sqlite_autoindex_xyzabc_1] do_test alter-11.1 { sqlite4_exec db {CREATE TABLE t11(%c6%c6)} execsql { ALTER TABLE t11 ADD COLUMN abc; Index: test/alter3.test ================================================================== --- test/alter3.test +++ test/alter3.test @@ -179,10 +179,15 @@ execsql { ALTER TABLE t1 ADD c; SELECT * FROM t1; } } {1 100 {} 2 300 {}} +if {!$has_codec} { + do_test alter3-3.3 { + get_file_format + } {3} +} ifcapable schema_version { do_test alter3-3.4 { execsql { PRAGMA schema_version; } @@ -210,10 +215,15 @@ execsql { ALTER TABLE t1 ADD c DEFAULT 'hello world'; SELECT * FROM t1; } } {1 100 {hello world} 2 300 {hello world}} +if {!$has_codec} { + do_test alter3-4.3 { + get_file_format + } {3} +} ifcapable schema_version { do_test alter3-4.4 { execsql { PRAGMA schema_version; } @@ -254,10 +264,15 @@ do_test alter3-5.4 { execsql { PRAGMA aux.schema_version; } } {31} + } + if {!$has_codec} { + do_test alter3-5.5 { + list [get_file_format test2.db] [get_file_format] + } {2 3} } do_test alter3-5.6 { execsql { ALTER TABLE aux.t1 ADD COLUMN d DEFAULT 1000; SELECT sql FROM aux.sqlite_master; @@ -316,10 +331,45 @@ SELECT * FROM log; } } {b 1 2 a 1 2 b 3 4 a 3 4} } +if {!$has_codec} { + ifcapable vacuum { + do_test alter3-7.1 { + execsql { + VACUUM; + } + get_file_format + } {1} + do_test alter3-7.2 { + execsql { + CREATE TABLE abc(a, b, c); + ALTER TABLE abc ADD d DEFAULT NULL; + } + get_file_format + } {2} + do_test alter3-7.3 { + execsql { + ALTER TABLE abc ADD e DEFAULT 10; + } + get_file_format + } {3} + do_test alter3-7.4 { + execsql { + ALTER TABLE abc ADD f DEFAULT NULL; + } + get_file_format + } {3} + do_test alter3-7.5 { + execsql { + VACUUM; + } + get_file_format + } {1} + } +} # Ticket #1183 - Make sure adding columns to large tables does not cause # memory corruption (as was the case before this bug was fixed). do_test alter3-8.1 { execsql { Index: test/analyze3.test ================================================================== --- test/analyze3.test +++ test/analyze3.test @@ -121,14 +121,14 @@ execsql ANALYZE } {} do_eqp_test analyze3-1.1.2 { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x? AND x0 AND x<1100 -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x? AND x200 AND x<300 } } {199 0 14850} do_test analyze3-1.1.5 { set l [string range "200" 0 end] @@ -170,14 +170,14 @@ ANALYZE; } } {} do_eqp_test analyze3-1.2.2 { SELECT sum(y) FROM t2 WHERE x>1 AND x<2 -} {0 0 0 {SEARCH TABLE t2 USING INDEX i2 (x>? AND x? AND x0 AND x<99 -} {0 0 0 {SEARCH TABLE t2 USING INDEX i2 (x>? AND x? AND x12 AND x<20 } } {161 0 4760} do_test analyze3-1.2.5 { set l [string range "12" 0 end] @@ -218,14 +218,14 @@ ANALYZE; } } {} do_eqp_test analyze3-1.3.2 { SELECT sum(y) FROM t3 WHERE x>200 AND x<300 -} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x? AND x0 AND x<1100 -} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x? AND x200 AND x<300 } } {199 0 14850} do_test analyze3-1.3.5 { @@ -273,14 +273,14 @@ } execsql COMMIT } {} do_eqp_test analyze3-2.2 { SELECT count(a) FROM t1 WHERE b LIKE 'a%' -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b>? AND b? AND b? AND b? AND b? AND b? AND b? AND c? AND c? AND c? AND c? AND owner_change_date? AND owner_change_date>32}] $r] set t1rx($r) $x set t1xr($x) $r puts " INSERT INTO t1(oid,a,x) VALUES($r,$a,'$x');" } puts " CREATE INDEX t1i1 ON t1(a);" @@ -132,11 +133,11 @@ puts "\175 {64}" puts "do_test $tname-1.3 \173" puts " db eval \173" puts " CREATE TABLE t2(r,a);" -puts " INSERT INTO t2 SELECT oid, a FROM t1;" +puts " INSERT INTO t2 SELECT rowid, a FROM t1;" puts " CREATE INDEX t2i1 ON t2(r);" puts " CREATE INDEX t2i2 ON t2(a);" puts " INSERT INTO t2 VALUES(9.22337303685477580800e+18,65);" set t1ra(9.22337303685477580800e+18) 65 set t1ar(65) 9.22337303685477580800e+18) @@ -155,26 +156,26 @@ foreach r $nums3 { incr i set r5 $r.5 set r0 $r.0 - if {abs($r)<0x7FFFFFFFFFFFFFFF || $r==-9223372036854775808} { + if {abs($r)<9.22337203685477580800e+18} { set x $t1rx($r) set a $t1ra($r) puts "do_test $tname-2.$i.1 \173" puts " db eval \173" - puts " SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=$r AND t2.a=t1.a" + puts " SELECT t1.* FROM t1, t2 WHERE t1.rowid=$r AND t2.a=t1.a" puts " \175" puts "\175 {$a $x}" puts "do_test $tname-2.$i.2 \173" puts " db eval \173" puts " SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='$x'" puts " \175" puts "\175 {$r $a}" puts "do_test $tname-2.$i.3 \173" puts " db eval \173" - puts " SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=$a" + puts " SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=$a" puts " \175" puts "\175 {$r $x}" } foreach op {> >= < <=} subno {gt ge lt le} { @@ -189,19 +190,19 @@ } } puts "do_test $tname-2.$i.$subno.1 \173" puts " db eval \173" puts " SELECT t2.a FROM t1 JOIN t2 USING(a)" - puts " WHERE t1.oid $op $r ORDER BY t2.a" + puts " WHERE t1.rowid $op $r ORDER BY t2.a" puts " \175" puts "\175 {[sort $aset]}" ################################################################ 2.x.y.2 puts "do_test $tname-2.$i.$subno.2 \173" puts " db eval \173" puts " SELECT t2.a FROM t2 NATURAL JOIN t1" - puts " WHERE t1.oid $op $r ORDER BY t1.a DESC" + puts " WHERE t1.rowid $op $r ORDER BY t1.a DESC" puts " \175" puts "\175 {[reverse [sort $aset]]}" ################################################################ 2.x.y.3 @@ -210,13 +211,13 @@ foreach rx [sort $rset] { lappend aset $t1ra($rx) } puts "do_test $tname-2.$i.$subno.3 \173" puts " db eval \173" - puts " SELECT t1.a FROM t1 JOIN t2 ON t1.oid $op t2.r" + puts " SELECT t1.a FROM t1 JOIN t2 ON t1.rowid $op t2.r" puts " WHERE t2.a=$ax" - puts " ORDER BY t1.oid" + puts " ORDER BY t1.rowid" puts " \175" puts "\175 {$aset}" ################################################################ 2.x.y.4 set aset {} @@ -223,13 +224,13 @@ foreach rx [reverse [sort $rset]] { lappend aset $t1ra($rx) } puts "do_test $tname-2.$i.$subno.4 \173" puts " db eval \173" - puts " SELECT t1.a FROM t1 JOIN t2 ON t1.oid $op t2.r" + puts " SELECT t1.a FROM t1 JOIN t2 ON t1.rowid $op t2.r" puts " WHERE t2.a=$ax" - puts " ORDER BY t1.oid DESC" + puts " ORDER BY t1.rowid DESC" puts " \175" puts "\175 {$aset}" ################################################################ 2.x.y.5 set aset {} @@ -241,11 +242,11 @@ set rx $t1xr($x) lappend aset $t1ra($rx) } puts "do_test $tname-2.$i.$subno.5 \173" puts " db eval \173" - puts " SELECT t1.a FROM t1 JOIN t2 ON t1.oid $op t2.r" + puts " SELECT t1.a FROM t1 JOIN t2 ON t1.rowid $op t2.r" puts " WHERE t2.a=$ax" puts " ORDER BY x" puts " \175" puts "\175 {$aset}" @@ -261,13 +262,13 @@ foreach rx [sort $rset] { lappend aset $t1ra($rx) } puts "do_test $tname-2.$i.$subno.10 \173" puts " db eval \173" - puts " SELECT t1.a FROM t1 JOIN t2 ON t1.oid $op CAST(t2.r AS real)" + puts " SELECT t1.a FROM t1 JOIN t2 ON t1.rowid $op CAST(t2.r AS real)" puts " WHERE t2.a=$ax" - puts " ORDER BY t1.oid" + puts " ORDER BY t1.rowid" puts " \175" puts "\175 {$aset}" ################################################################ 2.x.y.11 set aset {} @@ -274,16 +275,16 @@ foreach rx [reverse [sort $rset]] { lappend aset $t1ra($rx) } puts "do_test $tname-2.$i.$subno.11 \173" puts " db eval \173" - puts " SELECT t1.a FROM t1 JOIN t2 ON t1.oid $op CAST(t2.r AS real)" + puts " SELECT t1.a FROM t1 JOIN t2 ON t1.rowid $op CAST(t2.r AS real)" puts " WHERE t2.a=$ax" - puts " ORDER BY t1.oid DESC" + puts " ORDER BY t1.rowid DESC" puts " \175" puts "\175 {$aset}" } } puts {finish_test} Index: test/boundary3.test ================================================================== --- test/boundary3.test +++ test/boundary3.test @@ -11,20 +11,21 @@ # This file implements regression tests for SQLite library. # # This file is automatically generated from a separate TCL script. # This file seeks to exercise integer boundary values. # +# $Id: boundary3.test,v 1.2 2009/01/02 15:45:48 shane Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Many of the boundary tests depend on a working 64-bit implementation. if {![working_64bit_int]} { finish_test; return } do_test boundary3-1.1 { db eval { - CREATE TABLE t1(oid PRIMARY KEY, a,x); + CREATE TABLE t1(a,x); INSERT INTO t1(oid,a,x) VALUES(-8388609,1,'ffffffffff7fffff'); INSERT INTO t1(oid,a,x) VALUES(-36028797018963969,2,'ff7fffffffffffff'); INSERT INTO t1(oid,a,x) VALUES(9223372036854775807,3,'7fffffffffffffff'); INSERT INTO t1(oid,a,x) VALUES(127,4,'000000000000007f'); INSERT INTO t1(oid,a,x) VALUES(3,5,'0000000000000003'); @@ -97,12359 +98,12359 @@ } } {64} do_test boundary3-1.3 { db eval { CREATE TABLE t2(r,a); - INSERT INTO t2 SELECT oid, a FROM t1; + INSERT INTO t2 SELECT rowid, a FROM t1; CREATE INDEX t2i1 ON t2(r); CREATE INDEX t2i2 ON t2(a); INSERT INTO t2 VALUES(9.22337303685477580800e+18,65); INSERT INTO t2 VALUES(-9.22337303685477580800e+18,66); SELECT count(*) FROM t2; } } {66} do_test boundary3-2.1.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=72057594037927935 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=72057594037927935 AND t2.a=t1.a } } {17 00ffffffffffffff} do_test boundary3-2.1.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='00ffffffffffffff' } } {72057594037927935 17} do_test boundary3-2.1.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=17 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=17 } } {72057594037927935 00ffffffffffffff} do_test boundary3-2.1.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 72057594037927935 ORDER BY t2.a + WHERE t1.rowid > 72057594037927935 ORDER BY t2.a } } {3 28} do_test boundary3-2.1.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 72057594037927935 ORDER BY t1.a DESC + WHERE t1.rowid > 72057594037927935 ORDER BY t1.a DESC } } {28 3} do_test boundary3-2.1.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=17 - ORDER BY t1.oid + ORDER BY t1.rowid } } {28 3} do_test boundary3-2.1.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=17 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28} do_test boundary3-2.1.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=17 ORDER BY x } } {28 3} do_test boundary3-2.1.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 72057594037927935 ORDER BY t2.a + WHERE t1.rowid >= 72057594037927935 ORDER BY t2.a } } {3 17 28} do_test boundary3-2.1.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 72057594037927935 ORDER BY t1.a DESC + WHERE t1.rowid >= 72057594037927935 ORDER BY t1.a DESC } } {28 17 3} do_test boundary3-2.1.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=17 - ORDER BY t1.oid + ORDER BY t1.rowid } } {17 28 3} do_test boundary3-2.1.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=17 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17} do_test boundary3-2.1.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=17 ORDER BY x } } {17 28 3} do_test boundary3-2.1.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 72057594037927935 ORDER BY t2.a + WHERE t1.rowid < 72057594037927935 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 10 11 12 13 14 15 16 18 19 20 21 22 23 24 25 26 27 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.1.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 72057594037927935 ORDER BY t1.a DESC + WHERE t1.rowid < 72057594037927935 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 27 26 25 24 23 22 21 20 19 18 16 15 14 13 12 11 10 9 8 7 6 5 4 2 1} do_test boundary3-2.1.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=17 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45} do_test boundary3-2.1.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=17 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.1.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=17 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.1.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 72057594037927935 ORDER BY t2.a + WHERE t1.rowid <= 72057594037927935 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.1.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 72057594037927935 ORDER BY t1.a DESC + WHERE t1.rowid <= 72057594037927935 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 2 1} do_test boundary3-2.1.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=17 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17} do_test boundary3-2.1.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=17 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.1.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=17 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.2.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=16384 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=16384 AND t2.a=t1.a } } {16 0000000000004000} do_test boundary3-2.2.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000000004000' } } {16384 16} do_test boundary3-2.2.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=16 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=16 } } {16384 0000000000004000} do_test boundary3-2.2.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 16384 ORDER BY t2.a + WHERE t1.rowid > 16384 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 15 17 18 19 20 22 23 24 25 26 27 28 34 35 36 39 40 42 43 45 46 48 50 51 56 57 62} do_test boundary3-2.2.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 16384 ORDER BY t1.a DESC + WHERE t1.rowid > 16384 ORDER BY t1.a DESC } } {62 57 56 51 50 48 46 45 43 42 40 39 36 35 34 28 27 26 25 24 23 22 20 19 18 17 15 14 13 12 10 9 7 6 3} do_test boundary3-2.2.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=16 - ORDER BY t1.oid + ORDER BY t1.rowid } } {23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.2.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=16 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23} do_test boundary3-2.2.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=16 ORDER BY x } } {23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.2.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=16 - ORDER BY t1.oid + ORDER BY t1.rowid } } {23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.2.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=16 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23} do_test boundary3-2.2.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 16384 ORDER BY t2.a + WHERE t1.rowid >= 16384 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 34 35 36 39 40 42 43 45 46 48 50 51 56 57 62} do_test boundary3-2.2.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 16384 ORDER BY t1.a DESC + WHERE t1.rowid >= 16384 ORDER BY t1.a DESC } } {62 57 56 51 50 48 46 45 43 42 40 39 36 35 34 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 7 6 3} do_test boundary3-2.2.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=16 - ORDER BY t1.oid + ORDER BY t1.rowid } } {16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.2.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=16 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16} do_test boundary3-2.2.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=16 ORDER BY x } } {16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.2.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=16 - ORDER BY t1.oid + ORDER BY t1.rowid } } {16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.2.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=16 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16} do_test boundary3-2.2.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 16384 ORDER BY t2.a + WHERE t1.rowid < 16384 ORDER BY t2.a } } {1 2 4 5 8 11 21 29 30 31 32 33 37 38 41 44 47 49 52 53 54 55 58 59 60 61 63 64} do_test boundary3-2.2.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 16384 ORDER BY t1.a DESC + WHERE t1.rowid < 16384 ORDER BY t1.a DESC } } {64 63 61 60 59 58 55 54 53 52 49 47 44 41 38 37 33 32 31 30 29 21 11 8 5 4 2 1} do_test boundary3-2.2.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=16 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8} do_test boundary3-2.2.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=16 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.2.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=16 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.2.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=16 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8} do_test boundary3-2.2.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=16 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.2.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 16384 ORDER BY t2.a + WHERE t1.rowid <= 16384 ORDER BY t2.a } } {1 2 4 5 8 11 16 21 29 30 31 32 33 37 38 41 44 47 49 52 53 54 55 58 59 60 61 63 64} do_test boundary3-2.2.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 16384 ORDER BY t1.a DESC + WHERE t1.rowid <= 16384 ORDER BY t1.a DESC } } {64 63 61 60 59 58 55 54 53 52 49 47 44 41 38 37 33 32 31 30 29 21 16 11 8 5 4 2 1} do_test boundary3-2.2.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=16 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16} do_test boundary3-2.2.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=16 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.2.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=16 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.2.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=16 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16} do_test boundary3-2.2.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=16 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.3.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=4294967296 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=4294967296 AND t2.a=t1.a } } {36 0000000100000000} do_test boundary3-2.3.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000100000000' } } {4294967296 36} do_test boundary3-2.3.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=36 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=36 } } {4294967296 0000000100000000} do_test boundary3-2.3.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 4294967296 ORDER BY t2.a + WHERE t1.rowid > 4294967296 ORDER BY t2.a } } {3 7 10 13 17 19 22 25 26 27 28 34 35 39 43 45 46 56 57} do_test boundary3-2.3.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 4294967296 ORDER BY t1.a DESC + WHERE t1.rowid > 4294967296 ORDER BY t1.a DESC } } {57 56 46 45 43 39 35 34 28 27 26 25 22 19 17 13 10 7 3} do_test boundary3-2.3.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=36 - ORDER BY t1.oid + ORDER BY t1.rowid } } {39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.3.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=36 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39} do_test boundary3-2.3.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=36 ORDER BY x } } {39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.3.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=36 - ORDER BY t1.oid + ORDER BY t1.rowid } } {39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.3.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=36 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39} do_test boundary3-2.3.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 4294967296 ORDER BY t2.a + WHERE t1.rowid >= 4294967296 ORDER BY t2.a } } {3 7 10 13 17 19 22 25 26 27 28 34 35 36 39 43 45 46 56 57} do_test boundary3-2.3.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 4294967296 ORDER BY t1.a DESC + WHERE t1.rowid >= 4294967296 ORDER BY t1.a DESC } } {57 56 46 45 43 39 36 35 34 28 27 26 25 22 19 17 13 10 7 3} do_test boundary3-2.3.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=36 - ORDER BY t1.oid + ORDER BY t1.rowid } } {36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.3.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=36 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36} do_test boundary3-2.3.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=36 ORDER BY x } } {36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.3.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=36 - ORDER BY t1.oid + ORDER BY t1.rowid } } {36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.3.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=36 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36} do_test boundary3-2.3.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 4294967296 ORDER BY t2.a + WHERE t1.rowid < 4294967296 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 14 15 16 18 20 21 23 24 29 30 31 32 33 37 38 40 41 42 44 47 48 49 50 51 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.3.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 4294967296 ORDER BY t1.a DESC + WHERE t1.rowid < 4294967296 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 51 50 49 48 47 44 42 41 40 38 37 33 32 31 30 29 24 23 21 20 18 16 15 14 12 11 9 8 6 5 4 2 1} do_test boundary3-2.3.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=36 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14} do_test boundary3-2.3.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=36 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.3.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=36 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.3.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=36 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14} do_test boundary3-2.3.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=36 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.3.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 4294967296 ORDER BY t2.a + WHERE t1.rowid <= 4294967296 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 14 15 16 18 20 21 23 24 29 30 31 32 33 36 37 38 40 41 42 44 47 48 49 50 51 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.3.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 4294967296 ORDER BY t1.a DESC + WHERE t1.rowid <= 4294967296 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 51 50 49 48 47 44 42 41 40 38 37 36 33 32 31 30 29 24 23 21 20 18 16 15 14 12 11 9 8 6 5 4 2 1} do_test boundary3-2.3.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=36 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36} do_test boundary3-2.3.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=36 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.3.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=36 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.3.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=36 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36} do_test boundary3-2.3.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=36 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.4.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=16777216 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=16777216 AND t2.a=t1.a } } {6 0000000001000000} do_test boundary3-2.4.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000001000000' } } {16777216 6} do_test boundary3-2.4.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=6 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=6 } } {16777216 0000000001000000} do_test boundary3-2.4.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 16777216 ORDER BY t2.a + WHERE t1.rowid > 16777216 ORDER BY t2.a } } {3 7 10 12 13 14 17 19 20 22 25 26 27 28 34 35 36 39 40 43 45 46 51 56 57} do_test boundary3-2.4.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 16777216 ORDER BY t1.a DESC + WHERE t1.rowid > 16777216 ORDER BY t1.a DESC } } {57 56 51 46 45 43 40 39 36 35 34 28 27 26 25 22 20 19 17 14 13 12 10 7 3} do_test boundary3-2.4.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=6 - ORDER BY t1.oid + ORDER BY t1.rowid } } {12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.4.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=6 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12} do_test boundary3-2.4.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=6 ORDER BY x } } {12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.4.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=6 - ORDER BY t1.oid + ORDER BY t1.rowid } } {12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.4.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=6 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12} do_test boundary3-2.4.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 16777216 ORDER BY t2.a + WHERE t1.rowid >= 16777216 ORDER BY t2.a } } {3 6 7 10 12 13 14 17 19 20 22 25 26 27 28 34 35 36 39 40 43 45 46 51 56 57} do_test boundary3-2.4.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 16777216 ORDER BY t1.a DESC + WHERE t1.rowid >= 16777216 ORDER BY t1.a DESC } } {57 56 51 46 45 43 40 39 36 35 34 28 27 26 25 22 20 19 17 14 13 12 10 7 6 3} do_test boundary3-2.4.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=6 - ORDER BY t1.oid + ORDER BY t1.rowid } } {6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.4.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=6 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6} do_test boundary3-2.4.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=6 ORDER BY x } } {6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.4.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=6 - ORDER BY t1.oid + ORDER BY t1.rowid } } {6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.4.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=6 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6} do_test boundary3-2.4.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 16777216 ORDER BY t2.a + WHERE t1.rowid < 16777216 ORDER BY t2.a } } {1 2 4 5 8 9 11 15 16 18 21 23 24 29 30 31 32 33 37 38 41 42 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.4.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 16777216 ORDER BY t1.a DESC + WHERE t1.rowid < 16777216 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 42 41 38 37 33 32 31 30 29 24 23 21 18 16 15 11 9 8 5 4 2 1} do_test boundary3-2.4.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=6 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9} do_test boundary3-2.4.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=6 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.4.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=6 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.4.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=6 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9} do_test boundary3-2.4.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=6 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.4.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 16777216 ORDER BY t2.a + WHERE t1.rowid <= 16777216 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 15 16 18 21 23 24 29 30 31 32 33 37 38 41 42 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.4.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 16777216 ORDER BY t1.a DESC + WHERE t1.rowid <= 16777216 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 42 41 38 37 33 32 31 30 29 24 23 21 18 16 15 11 9 8 6 5 4 2 1} do_test boundary3-2.4.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=6 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6} do_test boundary3-2.4.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=6 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.4.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=6 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.4.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=6 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6} do_test boundary3-2.4.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=6 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.5.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=-32769 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=-32769 AND t2.a=t1.a } } {29 ffffffffffff7fff} do_test boundary3-2.5.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='ffffffffffff7fff' } } {-32769 29} do_test boundary3-2.5.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=29 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=29 } } {-32769 ffffffffffff7fff} do_test boundary3-2.5.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -32769 ORDER BY t2.a + WHERE t1.rowid > -32769 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 32 33 34 35 36 38 39 40 41 42 43 45 46 48 49 50 51 52 53 54 56 57 59 60 61 62} do_test boundary3-2.5.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -32769 ORDER BY t1.a DESC + WHERE t1.rowid > -32769 ORDER BY t1.a DESC } } {62 61 60 59 57 56 54 53 52 51 50 49 48 46 45 43 42 41 40 39 38 36 35 34 33 32 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.5.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=29 - ORDER BY t1.oid + ORDER BY t1.rowid } } {32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.5.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=29 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32} do_test boundary3-2.5.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=29 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 32 54 53 52 33 38} do_test boundary3-2.5.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=29 - ORDER BY t1.oid + ORDER BY t1.rowid } } {32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.5.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=29 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32} do_test boundary3-2.5.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -32769 ORDER BY t2.a + WHERE t1.rowid >= -32769 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 38 39 40 41 42 43 45 46 48 49 50 51 52 53 54 56 57 59 60 61 62} do_test boundary3-2.5.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -32769 ORDER BY t1.a DESC + WHERE t1.rowid >= -32769 ORDER BY t1.a DESC } } {62 61 60 59 57 56 54 53 52 51 50 49 48 46 45 43 42 41 40 39 38 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.5.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=29 - ORDER BY t1.oid + ORDER BY t1.rowid } } {29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.5.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=29 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29} do_test boundary3-2.5.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=29 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 29 32 54 53 52 33 38} do_test boundary3-2.5.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=29 - ORDER BY t1.oid + ORDER BY t1.rowid } } {29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.5.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=29 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29} do_test boundary3-2.5.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -32769 ORDER BY t2.a + WHERE t1.rowid < -32769 ORDER BY t2.a } } {1 2 11 21 37 44 47 55 58 63 64} do_test boundary3-2.5.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -32769 ORDER BY t1.a DESC + WHERE t1.rowid < -32769 ORDER BY t1.a DESC } } {64 63 58 55 47 44 37 21 11 2 1} do_test boundary3-2.5.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=29 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37} do_test boundary3-2.5.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=29 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.5.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=29 ORDER BY x } } {55 2 64 21 44 58 63 47 11 1 37} do_test boundary3-2.5.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=29 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37} do_test boundary3-2.5.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=29 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.5.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -32769 ORDER BY t2.a + WHERE t1.rowid <= -32769 ORDER BY t2.a } } {1 2 11 21 29 37 44 47 55 58 63 64} do_test boundary3-2.5.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -32769 ORDER BY t1.a DESC + WHERE t1.rowid <= -32769 ORDER BY t1.a DESC } } {64 63 58 55 47 44 37 29 21 11 2 1} do_test boundary3-2.5.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=29 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29} do_test boundary3-2.5.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=29 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.5.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=29 ORDER BY x } } {55 2 64 21 44 58 63 47 11 1 37 29} do_test boundary3-2.5.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=29 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29} do_test boundary3-2.5.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=29 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.6.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=-140737488355329 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=-140737488355329 AND t2.a=t1.a } } {21 ffff7fffffffffff} do_test boundary3-2.6.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='ffff7fffffffffff' } } {-140737488355329 21} do_test boundary3-2.6.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=21 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=21 } } {-140737488355329 ffff7fffffffffff} do_test boundary3-2.6.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -140737488355329 ORDER BY t2.a + WHERE t1.rowid > -140737488355329 ORDER BY t2.a } } {1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 56 57 58 59 60 61 62 63} do_test boundary3-2.6.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -140737488355329 ORDER BY t1.a DESC + WHERE t1.rowid > -140737488355329 ORDER BY t1.a DESC } } {63 62 61 60 59 58 57 56 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 1} do_test boundary3-2.6.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=21 - ORDER BY t1.oid + ORDER BY t1.rowid } } {44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.6.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=21 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44} do_test boundary3-2.6.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=21 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.6.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -140737488355329 ORDER BY t2.a + WHERE t1.rowid >= -140737488355329 ORDER BY t2.a } } {1 3 4 5 6 7 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 42 43 44 45 46 47 48 49 50 51 52 53 54 56 57 58 59 60 61 62 63} do_test boundary3-2.6.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -140737488355329 ORDER BY t1.a DESC + WHERE t1.rowid >= -140737488355329 ORDER BY t1.a DESC } } {63 62 61 60 59 58 57 56 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 1} do_test boundary3-2.6.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=21 - ORDER BY t1.oid + ORDER BY t1.rowid } } {21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.6.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=21 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21} do_test boundary3-2.6.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=21 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.6.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -140737488355329 ORDER BY t2.a + WHERE t1.rowid < -140737488355329 ORDER BY t2.a } } {2 55 64} do_test boundary3-2.6.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -140737488355329 ORDER BY t1.a DESC + WHERE t1.rowid < -140737488355329 ORDER BY t1.a DESC } } {64 55 2} do_test boundary3-2.6.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=21 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64} do_test boundary3-2.6.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=21 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {64 2 55} do_test boundary3-2.6.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=21 ORDER BY x } } {55 2 64} do_test boundary3-2.6.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -140737488355329 ORDER BY t2.a + WHERE t1.rowid <= -140737488355329 ORDER BY t2.a } } {2 21 55 64} do_test boundary3-2.6.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -140737488355329 ORDER BY t1.a DESC + WHERE t1.rowid <= -140737488355329 ORDER BY t1.a DESC } } {64 55 21 2} do_test boundary3-2.6.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=21 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21} do_test boundary3-2.6.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=21 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {21 64 2 55} do_test boundary3-2.6.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=21 ORDER BY x } } {55 2 64 21} do_test boundary3-2.7.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=2 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=2 AND t2.a=t1.a } } {41 0000000000000002} do_test boundary3-2.7.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000000000002' } } {2 41} do_test boundary3-2.7.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=41 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=41 } } {2 0000000000000002} do_test boundary3-2.7.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 2 ORDER BY t2.a + WHERE t1.rowid > 2 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 34 35 36 39 40 42 43 45 46 48 49 50 51 56 57 61 62} do_test boundary3-2.7.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 2 ORDER BY t1.a DESC + WHERE t1.rowid > 2 ORDER BY t1.a DESC } } {62 61 57 56 51 50 49 48 46 45 43 42 40 39 36 35 34 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.7.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=41 - ORDER BY t1.oid + ORDER BY t1.rowid } } {5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.7.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=41 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5} do_test boundary3-2.7.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=41 ORDER BY x } } {5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.7.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=41 - ORDER BY t1.oid + ORDER BY t1.rowid } } {5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.7.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=41 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5} do_test boundary3-2.7.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 2 ORDER BY t2.a + WHERE t1.rowid >= 2 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 34 35 36 39 40 41 42 43 45 46 48 49 50 51 56 57 61 62} do_test boundary3-2.7.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 2 ORDER BY t1.a DESC + WHERE t1.rowid >= 2 ORDER BY t1.a DESC } } {62 61 57 56 51 50 49 48 46 45 43 42 41 40 39 36 35 34 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.7.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=41 - ORDER BY t1.oid + ORDER BY t1.rowid } } {41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.7.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=41 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41} do_test boundary3-2.7.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=41 ORDER BY x } } {41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.7.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=41 - ORDER BY t1.oid + ORDER BY t1.rowid } } {41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.7.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=41 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41} do_test boundary3-2.7.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 2 ORDER BY t2.a + WHERE t1.rowid < 2 ORDER BY t2.a } } {1 2 11 21 29 32 33 37 38 44 47 52 53 54 55 58 59 60 63 64} do_test boundary3-2.7.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 2 ORDER BY t1.a DESC + WHERE t1.rowid < 2 ORDER BY t1.a DESC } } {64 63 60 59 58 55 54 53 52 47 44 38 37 33 32 29 21 11 2 1} do_test boundary3-2.7.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=41 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60} do_test boundary3-2.7.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=41 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.7.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=41 ORDER BY x } } {59 60 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.7.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=41 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60} do_test boundary3-2.7.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=41 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.7.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 2 ORDER BY t2.a + WHERE t1.rowid <= 2 ORDER BY t2.a } } {1 2 11 21 29 32 33 37 38 41 44 47 52 53 54 55 58 59 60 63 64} do_test boundary3-2.7.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 2 ORDER BY t1.a DESC + WHERE t1.rowid <= 2 ORDER BY t1.a DESC } } {64 63 60 59 58 55 54 53 52 47 44 41 38 37 33 32 29 21 11 2 1} do_test boundary3-2.7.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=41 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41} do_test boundary3-2.7.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=41 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.7.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=41 ORDER BY x } } {59 60 41 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.7.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=41 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41} do_test boundary3-2.7.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=41 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.8.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=4 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=4 AND t2.a=t1.a } } {31 0000000000000004} do_test boundary3-2.8.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000000000004' } } {4 31} do_test boundary3-2.8.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=31 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=31 } } {4 0000000000000004} do_test boundary3-2.8.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 4 ORDER BY t2.a + WHERE t1.rowid > 4 ORDER BY t2.a } } {3 4 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 34 35 36 39 40 42 43 45 46 48 49 50 51 56 57 61 62} do_test boundary3-2.8.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 4 ORDER BY t1.a DESC + WHERE t1.rowid > 4 ORDER BY t1.a DESC } } {62 61 57 56 51 50 49 48 46 45 43 42 40 39 36 35 34 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 4 3} do_test boundary3-2.8.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=31 - ORDER BY t1.oid + ORDER BY t1.rowid } } {4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.8.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=31 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4} do_test boundary3-2.8.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=31 ORDER BY x } } {4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.8.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=31 - ORDER BY t1.oid + ORDER BY t1.rowid } } {4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.8.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=31 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4} do_test boundary3-2.8.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 4 ORDER BY t2.a + WHERE t1.rowid >= 4 ORDER BY t2.a } } {3 4 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 34 35 36 39 40 42 43 45 46 48 49 50 51 56 57 61 62} do_test boundary3-2.8.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 4 ORDER BY t1.a DESC + WHERE t1.rowid >= 4 ORDER BY t1.a DESC } } {62 61 57 56 51 50 49 48 46 45 43 42 40 39 36 35 34 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 4 3} do_test boundary3-2.8.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=31 - ORDER BY t1.oid + ORDER BY t1.rowid } } {31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.8.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=31 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31} do_test boundary3-2.8.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=31 ORDER BY x } } {31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.8.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=31 - ORDER BY t1.oid + ORDER BY t1.rowid } } {31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.8.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=31 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31} do_test boundary3-2.8.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 4 ORDER BY t2.a + WHERE t1.rowid < 4 ORDER BY t2.a } } {1 2 5 11 21 29 32 33 37 38 41 44 47 52 53 54 55 58 59 60 63 64} do_test boundary3-2.8.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 4 ORDER BY t1.a DESC + WHERE t1.rowid < 4 ORDER BY t1.a DESC } } {64 63 60 59 58 55 54 53 52 47 44 41 38 37 33 32 29 21 11 5 2 1} do_test boundary3-2.8.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=31 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5} do_test boundary3-2.8.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=31 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.8.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=31 ORDER BY x } } {59 60 41 5 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.8.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=31 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5} do_test boundary3-2.8.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=31 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.8.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 4 ORDER BY t2.a + WHERE t1.rowid <= 4 ORDER BY t2.a } } {1 2 5 11 21 29 31 32 33 37 38 41 44 47 52 53 54 55 58 59 60 63 64} do_test boundary3-2.8.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 4 ORDER BY t1.a DESC + WHERE t1.rowid <= 4 ORDER BY t1.a DESC } } {64 63 60 59 58 55 54 53 52 47 44 41 38 37 33 32 31 29 21 11 5 2 1} do_test boundary3-2.8.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=31 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31} do_test boundary3-2.8.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=31 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.8.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=31 ORDER BY x } } {59 60 41 5 31 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.8.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=31 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31} do_test boundary3-2.8.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=31 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.9.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=562949953421311 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=562949953421311 AND t2.a=t1.a } } {13 0001ffffffffffff} do_test boundary3-2.9.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0001ffffffffffff' } } {562949953421311 13} do_test boundary3-2.9.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=13 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=13 } } {562949953421311 0001ffffffffffff} do_test boundary3-2.9.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 562949953421311 ORDER BY t2.a + WHERE t1.rowid > 562949953421311 ORDER BY t2.a } } {3 17 27 28 43 45} do_test boundary3-2.9.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 562949953421311 ORDER BY t1.a DESC + WHERE t1.rowid > 562949953421311 ORDER BY t1.a DESC } } {45 43 28 27 17 3} do_test boundary3-2.9.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=13 - ORDER BY t1.oid + ORDER BY t1.rowid } } {43 27 45 17 28 3} do_test boundary3-2.9.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=13 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43} do_test boundary3-2.9.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=13 ORDER BY x } } {43 27 45 17 28 3} do_test boundary3-2.9.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 562949953421311 ORDER BY t2.a + WHERE t1.rowid >= 562949953421311 ORDER BY t2.a } } {3 13 17 27 28 43 45} do_test boundary3-2.9.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 562949953421311 ORDER BY t1.a DESC + WHERE t1.rowid >= 562949953421311 ORDER BY t1.a DESC } } {45 43 28 27 17 13 3} do_test boundary3-2.9.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=13 - ORDER BY t1.oid + ORDER BY t1.rowid } } {13 43 27 45 17 28 3} do_test boundary3-2.9.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=13 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13} do_test boundary3-2.9.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=13 ORDER BY x } } {13 43 27 45 17 28 3} do_test boundary3-2.9.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 562949953421311 ORDER BY t2.a + WHERE t1.rowid < 562949953421311 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 10 11 12 14 15 16 18 19 20 21 22 23 24 25 26 29 30 31 32 33 34 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.9.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 562949953421311 ORDER BY t1.a DESC + WHERE t1.rowid < 562949953421311 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 34 33 32 31 30 29 26 25 24 23 22 21 20 19 18 16 15 14 12 11 10 9 8 7 6 5 4 2 1} do_test boundary3-2.9.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=13 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26} do_test boundary3-2.9.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=13 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.9.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=13 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.9.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 562949953421311 ORDER BY t2.a + WHERE t1.rowid <= 562949953421311 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 10 11 12 13 14 15 16 18 19 20 21 22 23 24 25 26 29 30 31 32 33 34 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.9.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 562949953421311 ORDER BY t1.a DESC + WHERE t1.rowid <= 562949953421311 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 34 33 32 31 30 29 26 25 24 23 22 21 20 19 18 16 15 14 13 12 11 10 9 8 7 6 5 4 2 1} do_test boundary3-2.9.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=13 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13} do_test boundary3-2.9.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=13 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.9.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=13 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.10.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=256 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=256 AND t2.a=t1.a } } {61 0000000000000100} do_test boundary3-2.10.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000000000100' } } {256 61} do_test boundary3-2.10.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=61 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=61 } } {256 0000000000000100} do_test boundary3-2.10.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 256 ORDER BY t2.a + WHERE t1.rowid > 256 ORDER BY t2.a } } {3 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 34 35 36 39 40 42 43 45 46 48 50 51 56 57 62} do_test boundary3-2.10.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 256 ORDER BY t1.a DESC + WHERE t1.rowid > 256 ORDER BY t1.a DESC } } {62 57 56 51 50 48 46 45 43 42 40 39 36 35 34 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 3} do_test boundary3-2.10.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=61 - ORDER BY t1.oid + ORDER BY t1.rowid } } {8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.10.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=61 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8} do_test boundary3-2.10.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=61 ORDER BY x } } {8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.10.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=61 - ORDER BY t1.oid + ORDER BY t1.rowid } } {8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.10.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=61 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8} do_test boundary3-2.10.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 256 ORDER BY t2.a + WHERE t1.rowid >= 256 ORDER BY t2.a } } {3 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 34 35 36 39 40 42 43 45 46 48 50 51 56 57 61 62} do_test boundary3-2.10.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 256 ORDER BY t1.a DESC + WHERE t1.rowid >= 256 ORDER BY t1.a DESC } } {62 61 57 56 51 50 48 46 45 43 42 40 39 36 35 34 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 3} do_test boundary3-2.10.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=61 - ORDER BY t1.oid + ORDER BY t1.rowid } } {61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.10.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=61 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61} do_test boundary3-2.10.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=61 ORDER BY x } } {61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.10.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=61 - ORDER BY t1.oid + ORDER BY t1.rowid } } {61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.10.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=61 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61} do_test boundary3-2.10.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 256 ORDER BY t2.a + WHERE t1.rowid < 256 ORDER BY t2.a } } {1 2 4 5 11 21 29 30 31 32 33 37 38 41 44 47 49 52 53 54 55 58 59 60 63 64} do_test boundary3-2.10.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 256 ORDER BY t1.a DESC + WHERE t1.rowid < 256 ORDER BY t1.a DESC } } {64 63 60 59 58 55 54 53 52 49 47 44 41 38 37 33 32 31 30 29 21 11 5 4 2 1} do_test boundary3-2.10.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=61 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30} do_test boundary3-2.10.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=61 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.10.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=61 ORDER BY x } } {59 60 41 5 31 4 49 30 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.10.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=61 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30} do_test boundary3-2.10.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=61 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.10.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 256 ORDER BY t2.a + WHERE t1.rowid <= 256 ORDER BY t2.a } } {1 2 4 5 11 21 29 30 31 32 33 37 38 41 44 47 49 52 53 54 55 58 59 60 61 63 64} do_test boundary3-2.10.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 256 ORDER BY t1.a DESC + WHERE t1.rowid <= 256 ORDER BY t1.a DESC } } {64 63 61 60 59 58 55 54 53 52 49 47 44 41 38 37 33 32 31 30 29 21 11 5 4 2 1} do_test boundary3-2.10.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=61 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61} do_test boundary3-2.10.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=61 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.10.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=61 ORDER BY x } } {59 60 41 5 31 4 49 30 61 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.10.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=61 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61} do_test boundary3-2.10.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=61 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.11.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=34359738368 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=34359738368 AND t2.a=t1.a } } {22 0000000800000000} do_test boundary3-2.11.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000800000000' } } {34359738368 22} do_test boundary3-2.11.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=22 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=22 } } {34359738368 0000000800000000} do_test boundary3-2.11.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 34359738368 ORDER BY t2.a + WHERE t1.rowid > 34359738368 ORDER BY t2.a } } {3 7 10 13 17 19 25 26 27 28 34 35 43 45 46 56 57} do_test boundary3-2.11.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 34359738368 ORDER BY t1.a DESC + WHERE t1.rowid > 34359738368 ORDER BY t1.a DESC } } {57 56 46 45 43 35 34 28 27 26 25 19 17 13 10 7 3} do_test boundary3-2.11.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=22 - ORDER BY t1.oid + ORDER BY t1.rowid } } {46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.11.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=22 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46} do_test boundary3-2.11.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=22 ORDER BY x } } {46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.11.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=22 - ORDER BY t1.oid + ORDER BY t1.rowid } } {46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.11.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=22 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46} do_test boundary3-2.11.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 34359738368 ORDER BY t2.a + WHERE t1.rowid >= 34359738368 ORDER BY t2.a } } {3 7 10 13 17 19 22 25 26 27 28 34 35 43 45 46 56 57} do_test boundary3-2.11.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 34359738368 ORDER BY t1.a DESC + WHERE t1.rowid >= 34359738368 ORDER BY t1.a DESC } } {57 56 46 45 43 35 34 28 27 26 25 22 19 17 13 10 7 3} do_test boundary3-2.11.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=22 - ORDER BY t1.oid + ORDER BY t1.rowid } } {22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.11.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=22 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22} do_test boundary3-2.11.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=22 ORDER BY x } } {22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.11.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=22 - ORDER BY t1.oid + ORDER BY t1.rowid } } {22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.11.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=22 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22} do_test boundary3-2.11.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 34359738368 ORDER BY t2.a + WHERE t1.rowid < 34359738368 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 14 15 16 18 20 21 23 24 29 30 31 32 33 36 37 38 39 40 41 42 44 47 48 49 50 51 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.11.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 34359738368 ORDER BY t1.a DESC + WHERE t1.rowid < 34359738368 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 51 50 49 48 47 44 42 41 40 39 38 37 36 33 32 31 30 29 24 23 21 20 18 16 15 14 12 11 9 8 6 5 4 2 1} do_test boundary3-2.11.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=22 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39} do_test boundary3-2.11.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=22 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.11.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=22 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.11.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=22 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39} do_test boundary3-2.11.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=22 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.11.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 34359738368 ORDER BY t2.a + WHERE t1.rowid <= 34359738368 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 14 15 16 18 20 21 22 23 24 29 30 31 32 33 36 37 38 39 40 41 42 44 47 48 49 50 51 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.11.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 34359738368 ORDER BY t1.a DESC + WHERE t1.rowid <= 34359738368 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 51 50 49 48 47 44 42 41 40 39 38 37 36 33 32 31 30 29 24 23 22 21 20 18 16 15 14 12 11 9 8 6 5 4 2 1} do_test boundary3-2.11.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=22 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22} do_test boundary3-2.11.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=22 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.11.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=22 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.11.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=22 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22} do_test boundary3-2.11.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=22 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.12.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=65536 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=65536 AND t2.a=t1.a } } {62 0000000000010000} do_test boundary3-2.12.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000000010000' } } {65536 62} do_test boundary3-2.12.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=62 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=62 } } {65536 0000000000010000} do_test boundary3-2.12.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 65536 ORDER BY t2.a + WHERE t1.rowid > 65536 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 15 17 18 19 20 22 24 25 26 27 28 34 35 36 39 40 42 43 45 46 51 56 57} do_test boundary3-2.12.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 65536 ORDER BY t1.a DESC + WHERE t1.rowid > 65536 ORDER BY t1.a DESC } } {57 56 51 46 45 43 42 40 39 36 35 34 28 27 26 25 24 22 20 19 18 17 15 14 13 12 10 9 7 6 3} do_test boundary3-2.12.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=62 - ORDER BY t1.oid + ORDER BY t1.rowid } } {15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.12.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=62 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15} do_test boundary3-2.12.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=62 ORDER BY x } } {15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.12.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=62 - ORDER BY t1.oid + ORDER BY t1.rowid } } {15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.12.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=62 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15} do_test boundary3-2.12.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 65536 ORDER BY t2.a + WHERE t1.rowid >= 65536 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 15 17 18 19 20 22 24 25 26 27 28 34 35 36 39 40 42 43 45 46 51 56 57 62} do_test boundary3-2.12.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 65536 ORDER BY t1.a DESC + WHERE t1.rowid >= 65536 ORDER BY t1.a DESC } } {62 57 56 51 46 45 43 42 40 39 36 35 34 28 27 26 25 24 22 20 19 18 17 15 14 13 12 10 9 7 6 3} do_test boundary3-2.12.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=62 - ORDER BY t1.oid + ORDER BY t1.rowid } } {62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.12.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=62 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62} do_test boundary3-2.12.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=62 ORDER BY x } } {62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.12.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=62 - ORDER BY t1.oid + ORDER BY t1.rowid } } {62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.12.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=62 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62} do_test boundary3-2.12.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 65536 ORDER BY t2.a + WHERE t1.rowid < 65536 ORDER BY t2.a } } {1 2 4 5 8 11 16 21 23 29 30 31 32 33 37 38 41 44 47 48 49 50 52 53 54 55 58 59 60 61 63 64} do_test boundary3-2.12.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 65536 ORDER BY t1.a DESC + WHERE t1.rowid < 65536 ORDER BY t1.a DESC } } {64 63 61 60 59 58 55 54 53 52 50 49 48 47 44 41 38 37 33 32 31 30 29 23 21 16 11 8 5 4 2 1} do_test boundary3-2.12.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=62 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48} do_test boundary3-2.12.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=62 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.12.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=62 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.12.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=62 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48} do_test boundary3-2.12.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=62 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.12.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 65536 ORDER BY t2.a + WHERE t1.rowid <= 65536 ORDER BY t2.a } } {1 2 4 5 8 11 16 21 23 29 30 31 32 33 37 38 41 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.12.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 65536 ORDER BY t1.a DESC + WHERE t1.rowid <= 65536 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 41 38 37 33 32 31 30 29 23 21 16 11 8 5 4 2 1} do_test boundary3-2.12.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=62 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62} do_test boundary3-2.12.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=62 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.12.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=62 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.12.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=62 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62} do_test boundary3-2.12.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=62 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.13.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=268435456 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=268435456 AND t2.a=t1.a } } {40 0000000010000000} do_test boundary3-2.13.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000010000000' } } {268435456 40} do_test boundary3-2.13.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=40 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=40 } } {268435456 0000000010000000} do_test boundary3-2.13.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 268435456 ORDER BY t2.a + WHERE t1.rowid > 268435456 ORDER BY t2.a } } {3 7 10 13 14 17 19 20 22 25 26 27 28 34 35 36 39 43 45 46 51 56 57} do_test boundary3-2.13.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 268435456 ORDER BY t1.a DESC + WHERE t1.rowid > 268435456 ORDER BY t1.a DESC } } {57 56 51 46 45 43 39 36 35 34 28 27 26 25 22 20 19 17 14 13 10 7 3} do_test boundary3-2.13.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=40 - ORDER BY t1.oid + ORDER BY t1.rowid } } {20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.13.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=40 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20} do_test boundary3-2.13.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=40 ORDER BY x } } {20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.13.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=40 - ORDER BY t1.oid + ORDER BY t1.rowid } } {20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.13.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=40 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20} do_test boundary3-2.13.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 268435456 ORDER BY t2.a + WHERE t1.rowid >= 268435456 ORDER BY t2.a } } {3 7 10 13 14 17 19 20 22 25 26 27 28 34 35 36 39 40 43 45 46 51 56 57} do_test boundary3-2.13.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 268435456 ORDER BY t1.a DESC + WHERE t1.rowid >= 268435456 ORDER BY t1.a DESC } } {57 56 51 46 45 43 40 39 36 35 34 28 27 26 25 22 20 19 17 14 13 10 7 3} do_test boundary3-2.13.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=40 - ORDER BY t1.oid + ORDER BY t1.rowid } } {40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.13.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=40 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40} do_test boundary3-2.13.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=40 ORDER BY x } } {40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.13.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=40 - ORDER BY t1.oid + ORDER BY t1.rowid } } {40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.13.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=40 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40} do_test boundary3-2.13.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 268435456 ORDER BY t2.a + WHERE t1.rowid < 268435456 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 15 16 18 21 23 24 29 30 31 32 33 37 38 41 42 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.13.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 268435456 ORDER BY t1.a DESC + WHERE t1.rowid < 268435456 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 42 41 38 37 33 32 31 30 29 24 23 21 18 16 15 12 11 9 8 6 5 4 2 1} do_test boundary3-2.13.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=40 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12} do_test boundary3-2.13.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=40 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.13.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=40 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.13.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=40 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12} do_test boundary3-2.13.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=40 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.13.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 268435456 ORDER BY t2.a + WHERE t1.rowid <= 268435456 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 15 16 18 21 23 24 29 30 31 32 33 37 38 40 41 42 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.13.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 268435456 ORDER BY t1.a DESC + WHERE t1.rowid <= 268435456 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 42 41 40 38 37 33 32 31 30 29 24 23 21 18 16 15 12 11 9 8 6 5 4 2 1} do_test boundary3-2.13.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=40 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40} do_test boundary3-2.13.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=40 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.13.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=40 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.13.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=40 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40} do_test boundary3-2.13.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=40 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.14.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=-140737488355328 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=-140737488355328 AND t2.a=t1.a } } {44 ffff800000000000} do_test boundary3-2.14.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='ffff800000000000' } } {-140737488355328 44} do_test boundary3-2.14.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=44 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=44 } } {-140737488355328 ffff800000000000} do_test boundary3-2.14.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -140737488355328 ORDER BY t2.a + WHERE t1.rowid > -140737488355328 ORDER BY t2.a } } {1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 45 46 47 48 49 50 51 52 53 54 56 57 58 59 60 61 62 63} do_test boundary3-2.14.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -140737488355328 ORDER BY t1.a DESC + WHERE t1.rowid > -140737488355328 ORDER BY t1.a DESC } } {63 62 61 60 59 58 57 56 54 53 52 51 50 49 48 47 46 45 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 1} do_test boundary3-2.14.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=44 - ORDER BY t1.oid + ORDER BY t1.rowid } } {58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.14.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=44 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58} do_test boundary3-2.14.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=44 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.14.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -140737488355328 ORDER BY t2.a + WHERE t1.rowid >= -140737488355328 ORDER BY t2.a } } {1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 56 57 58 59 60 61 62 63} do_test boundary3-2.14.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -140737488355328 ORDER BY t1.a DESC + WHERE t1.rowid >= -140737488355328 ORDER BY t1.a DESC } } {63 62 61 60 59 58 57 56 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 1} do_test boundary3-2.14.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=44 - ORDER BY t1.oid + ORDER BY t1.rowid } } {44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.14.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=44 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44} do_test boundary3-2.14.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=44 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.14.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -140737488355328 ORDER BY t2.a + WHERE t1.rowid < -140737488355328 ORDER BY t2.a } } {2 21 55 64} do_test boundary3-2.14.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -140737488355328 ORDER BY t1.a DESC + WHERE t1.rowid < -140737488355328 ORDER BY t1.a DESC } } {64 55 21 2} do_test boundary3-2.14.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=44 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21} do_test boundary3-2.14.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=44 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {21 64 2 55} do_test boundary3-2.14.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=44 ORDER BY x } } {55 2 64 21} do_test boundary3-2.14.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -140737488355328 ORDER BY t2.a + WHERE t1.rowid <= -140737488355328 ORDER BY t2.a } } {2 21 44 55 64} do_test boundary3-2.14.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -140737488355328 ORDER BY t1.a DESC + WHERE t1.rowid <= -140737488355328 ORDER BY t1.a DESC } } {64 55 44 21 2} do_test boundary3-2.14.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=44 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44} do_test boundary3-2.14.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=44 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {44 21 64 2 55} do_test boundary3-2.14.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=44 ORDER BY x } } {55 2 64 21 44} do_test boundary3-2.15.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=1099511627776 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=1099511627776 AND t2.a=t1.a } } {19 0000010000000000} do_test boundary3-2.15.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000010000000000' } } {1099511627776 19} do_test boundary3-2.15.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=19 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=19 } } {1099511627776 0000010000000000} do_test boundary3-2.15.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 1099511627776 ORDER BY t2.a + WHERE t1.rowid > 1099511627776 ORDER BY t2.a } } {3 7 10 13 17 25 26 27 28 34 43 45 56} do_test boundary3-2.15.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 1099511627776 ORDER BY t1.a DESC + WHERE t1.rowid > 1099511627776 ORDER BY t1.a DESC } } {56 45 43 34 28 27 26 25 17 13 10 7 3} do_test boundary3-2.15.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=19 - ORDER BY t1.oid + ORDER BY t1.rowid } } {7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.15.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=19 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7} do_test boundary3-2.15.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=19 ORDER BY x } } {7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.15.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=19 - ORDER BY t1.oid + ORDER BY t1.rowid } } {7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.15.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=19 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7} do_test boundary3-2.15.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 1099511627776 ORDER BY t2.a + WHERE t1.rowid >= 1099511627776 ORDER BY t2.a } } {3 7 10 13 17 19 25 26 27 28 34 43 45 56} do_test boundary3-2.15.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 1099511627776 ORDER BY t1.a DESC + WHERE t1.rowid >= 1099511627776 ORDER BY t1.a DESC } } {56 45 43 34 28 27 26 25 19 17 13 10 7 3} do_test boundary3-2.15.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=19 - ORDER BY t1.oid + ORDER BY t1.rowid } } {19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.15.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=19 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19} do_test boundary3-2.15.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=19 ORDER BY x } } {19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.15.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=19 - ORDER BY t1.oid + ORDER BY t1.rowid } } {19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.15.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=19 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19} do_test boundary3-2.15.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 1099511627776 ORDER BY t2.a + WHERE t1.rowid < 1099511627776 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 14 15 16 18 20 21 22 23 24 29 30 31 32 33 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 57 58 59 60 61 62 63 64} do_test boundary3-2.15.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 1099511627776 ORDER BY t1.a DESC + WHERE t1.rowid < 1099511627776 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 33 32 31 30 29 24 23 22 21 20 18 16 15 14 12 11 9 8 6 5 4 2 1} do_test boundary3-2.15.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=19 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57} do_test boundary3-2.15.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=19 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.15.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=19 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.15.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=19 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57} do_test boundary3-2.15.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=19 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.15.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 1099511627776 ORDER BY t2.a + WHERE t1.rowid <= 1099511627776 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 14 15 16 18 19 20 21 22 23 24 29 30 31 32 33 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 57 58 59 60 61 62 63 64} do_test boundary3-2.15.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 1099511627776 ORDER BY t1.a DESC + WHERE t1.rowid <= 1099511627776 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 33 32 31 30 29 24 23 22 21 20 19 18 16 15 14 12 11 9 8 6 5 4 2 1} do_test boundary3-2.15.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=19 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19} do_test boundary3-2.15.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=19 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.15.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=19 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.15.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=19 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19} do_test boundary3-2.15.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=19 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.16.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 9223372036854775807 ORDER BY t2.a + WHERE t1.rowid > 9223372036854775807 ORDER BY t2.a } } {} do_test boundary3-2.16.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 9223372036854775807 ORDER BY t1.a DESC + WHERE t1.rowid > 9223372036854775807 ORDER BY t1.a DESC } } {} do_test boundary3-2.16.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=3 - ORDER BY t1.oid + ORDER BY t1.rowid } } {} do_test boundary3-2.16.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=3 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {} do_test boundary3-2.16.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=3 ORDER BY x } } {} do_test boundary3-2.16.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 9223372036854775807 ORDER BY t2.a + WHERE t1.rowid >= 9223372036854775807 ORDER BY t2.a } } {3} do_test boundary3-2.16.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 9223372036854775807 ORDER BY t1.a DESC + WHERE t1.rowid >= 9223372036854775807 ORDER BY t1.a DESC } } {3} do_test boundary3-2.16.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=3 - ORDER BY t1.oid + ORDER BY t1.rowid } } {3} do_test boundary3-2.16.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=3 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3} do_test boundary3-2.16.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=3 ORDER BY x } } {3} do_test boundary3-2.16.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 9223372036854775807 ORDER BY t2.a + WHERE t1.rowid < 9223372036854775807 ORDER BY t2.a } } {1 2 4 5 6 7 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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.16.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 9223372036854775807 ORDER BY t1.a DESC + WHERE t1.rowid < 9223372036854775807 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 2 1} do_test boundary3-2.16.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=3 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28} do_test boundary3-2.16.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=3 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.16.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=3 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.16.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 9223372036854775807 ORDER BY t2.a + WHERE t1.rowid <= 9223372036854775807 ORDER BY t2.a } } {1 2 3 4 5 6 7 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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.16.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 9223372036854775807 ORDER BY t1.a DESC + WHERE t1.rowid <= 9223372036854775807 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1} do_test boundary3-2.16.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=3 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.16.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=3 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.16.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=3 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.17.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=32768 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=32768 AND t2.a=t1.a } } {50 0000000000008000} do_test boundary3-2.17.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000000008000' } } {32768 50} do_test boundary3-2.17.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=50 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=50 } } {32768 0000000000008000} do_test boundary3-2.17.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 32768 ORDER BY t2.a + WHERE t1.rowid > 32768 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 15 17 18 19 20 22 24 25 26 27 28 34 35 36 39 40 42 43 45 46 48 51 56 57 62} do_test boundary3-2.17.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 32768 ORDER BY t1.a DESC + WHERE t1.rowid > 32768 ORDER BY t1.a DESC } } {62 57 56 51 48 46 45 43 42 40 39 36 35 34 28 27 26 25 24 22 20 19 18 17 15 14 13 12 10 9 7 6 3} do_test boundary3-2.17.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=50 - ORDER BY t1.oid + ORDER BY t1.rowid } } {48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.17.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=50 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48} do_test boundary3-2.17.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=50 ORDER BY x } } {48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.17.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=50 - ORDER BY t1.oid + ORDER BY t1.rowid } } {48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.17.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=50 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48} do_test boundary3-2.17.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 32768 ORDER BY t2.a + WHERE t1.rowid >= 32768 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 15 17 18 19 20 22 24 25 26 27 28 34 35 36 39 40 42 43 45 46 48 50 51 56 57 62} do_test boundary3-2.17.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 32768 ORDER BY t1.a DESC + WHERE t1.rowid >= 32768 ORDER BY t1.a DESC } } {62 57 56 51 50 48 46 45 43 42 40 39 36 35 34 28 27 26 25 24 22 20 19 18 17 15 14 13 12 10 9 7 6 3} do_test boundary3-2.17.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=50 - ORDER BY t1.oid + ORDER BY t1.rowid } } {50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.17.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=50 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50} do_test boundary3-2.17.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=50 ORDER BY x } } {50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.17.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=50 - ORDER BY t1.oid + ORDER BY t1.rowid } } {50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.17.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=50 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50} do_test boundary3-2.17.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 32768 ORDER BY t2.a + WHERE t1.rowid < 32768 ORDER BY t2.a } } {1 2 4 5 8 11 16 21 23 29 30 31 32 33 37 38 41 44 47 49 52 53 54 55 58 59 60 61 63 64} do_test boundary3-2.17.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 32768 ORDER BY t1.a DESC + WHERE t1.rowid < 32768 ORDER BY t1.a DESC } } {64 63 61 60 59 58 55 54 53 52 49 47 44 41 38 37 33 32 31 30 29 23 21 16 11 8 5 4 2 1} do_test boundary3-2.17.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=50 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23} do_test boundary3-2.17.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=50 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.17.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=50 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.17.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=50 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23} do_test boundary3-2.17.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=50 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.17.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 32768 ORDER BY t2.a + WHERE t1.rowid <= 32768 ORDER BY t2.a } } {1 2 4 5 8 11 16 21 23 29 30 31 32 33 37 38 41 44 47 49 50 52 53 54 55 58 59 60 61 63 64} do_test boundary3-2.17.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 32768 ORDER BY t1.a DESC + WHERE t1.rowid <= 32768 ORDER BY t1.a DESC } } {64 63 61 60 59 58 55 54 53 52 50 49 47 44 41 38 37 33 32 31 30 29 23 21 16 11 8 5 4 2 1} do_test boundary3-2.17.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=50 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50} do_test boundary3-2.17.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=50 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.17.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=50 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.17.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=50 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50} do_test boundary3-2.17.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=50 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.18.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=-36028797018963968 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=-36028797018963968 AND t2.a=t1.a } } {64 ff80000000000000} do_test boundary3-2.18.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='ff80000000000000' } } {-36028797018963968 64} do_test boundary3-2.18.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=64 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=64 } } {-36028797018963968 ff80000000000000} do_test boundary3-2.18.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -36028797018963968 ORDER BY t2.a + WHERE t1.rowid > -36028797018963968 ORDER BY t2.a } } {1 3 4 5 6 7 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 42 43 44 45 46 47 48 49 50 51 52 53 54 56 57 58 59 60 61 62 63} do_test boundary3-2.18.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -36028797018963968 ORDER BY t1.a DESC + WHERE t1.rowid > -36028797018963968 ORDER BY t1.a DESC } } {63 62 61 60 59 58 57 56 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 1} do_test boundary3-2.18.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=64 - ORDER BY t1.oid + ORDER BY t1.rowid } } {21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.18.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=64 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21} do_test boundary3-2.18.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=64 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.18.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -36028797018963968 ORDER BY t2.a + WHERE t1.rowid >= -36028797018963968 ORDER BY t2.a } } {1 3 4 5 6 7 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 42 43 44 45 46 47 48 49 50 51 52 53 54 56 57 58 59 60 61 62 63 64} do_test boundary3-2.18.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -36028797018963968 ORDER BY t1.a DESC + WHERE t1.rowid >= -36028797018963968 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 1} do_test boundary3-2.18.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=64 - ORDER BY t1.oid + ORDER BY t1.rowid } } {64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.18.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=64 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64} do_test boundary3-2.18.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=64 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.18.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -36028797018963968 ORDER BY t2.a + WHERE t1.rowid < -36028797018963968 ORDER BY t2.a } } {2 55} do_test boundary3-2.18.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -36028797018963968 ORDER BY t1.a DESC + WHERE t1.rowid < -36028797018963968 ORDER BY t1.a DESC } } {55 2} do_test boundary3-2.18.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=64 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2} do_test boundary3-2.18.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=64 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {2 55} do_test boundary3-2.18.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=64 ORDER BY x } } {55 2} do_test boundary3-2.18.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -36028797018963968 ORDER BY t2.a + WHERE t1.rowid <= -36028797018963968 ORDER BY t2.a } } {2 55 64} do_test boundary3-2.18.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -36028797018963968 ORDER BY t1.a DESC + WHERE t1.rowid <= -36028797018963968 ORDER BY t1.a DESC } } {64 55 2} do_test boundary3-2.18.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=64 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64} do_test boundary3-2.18.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=64 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {64 2 55} do_test boundary3-2.18.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=64 ORDER BY x } } {55 2 64} do_test boundary3-2.19.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=65535 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=65535 AND t2.a=t1.a } } {48 000000000000ffff} do_test boundary3-2.19.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='000000000000ffff' } } {65535 48} do_test boundary3-2.19.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=48 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=48 } } {65535 000000000000ffff} do_test boundary3-2.19.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 65535 ORDER BY t2.a + WHERE t1.rowid > 65535 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 15 17 18 19 20 22 24 25 26 27 28 34 35 36 39 40 42 43 45 46 51 56 57 62} do_test boundary3-2.19.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 65535 ORDER BY t1.a DESC + WHERE t1.rowid > 65535 ORDER BY t1.a DESC } } {62 57 56 51 46 45 43 42 40 39 36 35 34 28 27 26 25 24 22 20 19 18 17 15 14 13 12 10 9 7 6 3} do_test boundary3-2.19.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=48 - ORDER BY t1.oid + ORDER BY t1.rowid } } {62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.19.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=48 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62} do_test boundary3-2.19.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=48 ORDER BY x } } {62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.19.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=48 - ORDER BY t1.oid + ORDER BY t1.rowid } } {62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.19.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=48 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62} do_test boundary3-2.19.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 65535 ORDER BY t2.a + WHERE t1.rowid >= 65535 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 15 17 18 19 20 22 24 25 26 27 28 34 35 36 39 40 42 43 45 46 48 51 56 57 62} do_test boundary3-2.19.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 65535 ORDER BY t1.a DESC + WHERE t1.rowid >= 65535 ORDER BY t1.a DESC } } {62 57 56 51 48 46 45 43 42 40 39 36 35 34 28 27 26 25 24 22 20 19 18 17 15 14 13 12 10 9 7 6 3} do_test boundary3-2.19.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=48 - ORDER BY t1.oid + ORDER BY t1.rowid } } {48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.19.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=48 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48} do_test boundary3-2.19.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=48 ORDER BY x } } {48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.19.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=48 - ORDER BY t1.oid + ORDER BY t1.rowid } } {48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.19.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=48 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48} do_test boundary3-2.19.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 65535 ORDER BY t2.a + WHERE t1.rowid < 65535 ORDER BY t2.a } } {1 2 4 5 8 11 16 21 23 29 30 31 32 33 37 38 41 44 47 49 50 52 53 54 55 58 59 60 61 63 64} do_test boundary3-2.19.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 65535 ORDER BY t1.a DESC + WHERE t1.rowid < 65535 ORDER BY t1.a DESC } } {64 63 61 60 59 58 55 54 53 52 50 49 47 44 41 38 37 33 32 31 30 29 23 21 16 11 8 5 4 2 1} do_test boundary3-2.19.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=48 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50} do_test boundary3-2.19.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=48 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.19.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=48 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.19.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=48 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50} do_test boundary3-2.19.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=48 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.19.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 65535 ORDER BY t2.a + WHERE t1.rowid <= 65535 ORDER BY t2.a } } {1 2 4 5 8 11 16 21 23 29 30 31 32 33 37 38 41 44 47 48 49 50 52 53 54 55 58 59 60 61 63 64} do_test boundary3-2.19.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 65535 ORDER BY t1.a DESC + WHERE t1.rowid <= 65535 ORDER BY t1.a DESC } } {64 63 61 60 59 58 55 54 53 52 50 49 48 47 44 41 38 37 33 32 31 30 29 23 21 16 11 8 5 4 2 1} do_test boundary3-2.19.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=48 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48} do_test boundary3-2.19.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=48 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.19.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=48 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.19.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=48 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48} do_test boundary3-2.19.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=48 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.20.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=4294967295 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=4294967295 AND t2.a=t1.a } } {14 00000000ffffffff} do_test boundary3-2.20.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='00000000ffffffff' } } {4294967295 14} do_test boundary3-2.20.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=14 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=14 } } {4294967295 00000000ffffffff} do_test boundary3-2.20.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 4294967295 ORDER BY t2.a + WHERE t1.rowid > 4294967295 ORDER BY t2.a } } {3 7 10 13 17 19 22 25 26 27 28 34 35 36 39 43 45 46 56 57} do_test boundary3-2.20.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 4294967295 ORDER BY t1.a DESC + WHERE t1.rowid > 4294967295 ORDER BY t1.a DESC } } {57 56 46 45 43 39 36 35 34 28 27 26 25 22 19 17 13 10 7 3} do_test boundary3-2.20.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=14 - ORDER BY t1.oid + ORDER BY t1.rowid } } {36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.20.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=14 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36} do_test boundary3-2.20.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=14 ORDER BY x } } {36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.20.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=14 - ORDER BY t1.oid + ORDER BY t1.rowid } } {36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.20.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=14 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36} do_test boundary3-2.20.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 4294967295 ORDER BY t2.a + WHERE t1.rowid >= 4294967295 ORDER BY t2.a } } {3 7 10 13 14 17 19 22 25 26 27 28 34 35 36 39 43 45 46 56 57} do_test boundary3-2.20.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 4294967295 ORDER BY t1.a DESC + WHERE t1.rowid >= 4294967295 ORDER BY t1.a DESC } } {57 56 46 45 43 39 36 35 34 28 27 26 25 22 19 17 14 13 10 7 3} do_test boundary3-2.20.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=14 - ORDER BY t1.oid + ORDER BY t1.rowid } } {14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.20.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=14 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14} do_test boundary3-2.20.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=14 ORDER BY x } } {14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.20.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=14 - ORDER BY t1.oid + ORDER BY t1.rowid } } {14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.20.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=14 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14} do_test boundary3-2.20.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 4294967295 ORDER BY t2.a + WHERE t1.rowid < 4294967295 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 15 16 18 20 21 23 24 29 30 31 32 33 37 38 40 41 42 44 47 48 49 50 51 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.20.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 4294967295 ORDER BY t1.a DESC + WHERE t1.rowid < 4294967295 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 51 50 49 48 47 44 42 41 40 38 37 33 32 31 30 29 24 23 21 20 18 16 15 12 11 9 8 6 5 4 2 1} do_test boundary3-2.20.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=14 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51} do_test boundary3-2.20.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=14 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.20.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=14 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.20.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=14 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51} do_test boundary3-2.20.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=14 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.20.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 4294967295 ORDER BY t2.a + WHERE t1.rowid <= 4294967295 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 14 15 16 18 20 21 23 24 29 30 31 32 33 37 38 40 41 42 44 47 48 49 50 51 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.20.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 4294967295 ORDER BY t1.a DESC + WHERE t1.rowid <= 4294967295 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 51 50 49 48 47 44 42 41 40 38 37 33 32 31 30 29 24 23 21 20 18 16 15 14 12 11 9 8 6 5 4 2 1} do_test boundary3-2.20.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=14 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14} do_test boundary3-2.20.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=14 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.20.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=14 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.20.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=14 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14} do_test boundary3-2.20.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=14 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.21.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=1099511627775 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=1099511627775 AND t2.a=t1.a } } {57 000000ffffffffff} do_test boundary3-2.21.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='000000ffffffffff' } } {1099511627775 57} do_test boundary3-2.21.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=57 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=57 } } {1099511627775 000000ffffffffff} do_test boundary3-2.21.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 1099511627775 ORDER BY t2.a + WHERE t1.rowid > 1099511627775 ORDER BY t2.a } } {3 7 10 13 17 19 25 26 27 28 34 43 45 56} do_test boundary3-2.21.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 1099511627775 ORDER BY t1.a DESC + WHERE t1.rowid > 1099511627775 ORDER BY t1.a DESC } } {56 45 43 34 28 27 26 25 19 17 13 10 7 3} do_test boundary3-2.21.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=57 - ORDER BY t1.oid + ORDER BY t1.rowid } } {19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.21.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=57 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19} do_test boundary3-2.21.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=57 ORDER BY x } } {19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.21.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=57 - ORDER BY t1.oid + ORDER BY t1.rowid } } {19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.21.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=57 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19} do_test boundary3-2.21.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 1099511627775 ORDER BY t2.a + WHERE t1.rowid >= 1099511627775 ORDER BY t2.a } } {3 7 10 13 17 19 25 26 27 28 34 43 45 56 57} do_test boundary3-2.21.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 1099511627775 ORDER BY t1.a DESC + WHERE t1.rowid >= 1099511627775 ORDER BY t1.a DESC } } {57 56 45 43 34 28 27 26 25 19 17 13 10 7 3} do_test boundary3-2.21.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=57 - ORDER BY t1.oid + ORDER BY t1.rowid } } {57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.21.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=57 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57} do_test boundary3-2.21.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=57 ORDER BY x } } {57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.21.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=57 - ORDER BY t1.oid + ORDER BY t1.rowid } } {57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.21.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=57 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57} do_test boundary3-2.21.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 1099511627775 ORDER BY t2.a + WHERE t1.rowid < 1099511627775 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 14 15 16 18 20 21 22 23 24 29 30 31 32 33 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.21.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 1099511627775 ORDER BY t1.a DESC + WHERE t1.rowid < 1099511627775 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 33 32 31 30 29 24 23 22 21 20 18 16 15 14 12 11 9 8 6 5 4 2 1} do_test boundary3-2.21.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=57 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35} do_test boundary3-2.21.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=57 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.21.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=57 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.21.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=57 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35} do_test boundary3-2.21.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=57 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.21.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 1099511627775 ORDER BY t2.a + WHERE t1.rowid <= 1099511627775 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 14 15 16 18 20 21 22 23 24 29 30 31 32 33 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 57 58 59 60 61 62 63 64} do_test boundary3-2.21.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 1099511627775 ORDER BY t1.a DESC + WHERE t1.rowid <= 1099511627775 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 33 32 31 30 29 24 23 22 21 20 18 16 15 14 12 11 9 8 6 5 4 2 1} do_test boundary3-2.21.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=57 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57} do_test boundary3-2.21.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=57 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.21.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=57 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.21.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=57 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57} do_test boundary3-2.21.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=57 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.22.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=-8388608 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=-8388608 AND t2.a=t1.a } } {37 ffffffffff800000} do_test boundary3-2.22.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='ffffffffff800000' } } {-8388608 37} do_test boundary3-2.22.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=37 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=37 } } {-8388608 ffffffffff800000} do_test boundary3-2.22.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -8388608 ORDER BY t2.a + WHERE t1.rowid > -8388608 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 38 39 40 41 42 43 45 46 48 49 50 51 52 53 54 56 57 59 60 61 62} do_test boundary3-2.22.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -8388608 ORDER BY t1.a DESC + WHERE t1.rowid > -8388608 ORDER BY t1.a DESC } } {62 61 60 59 57 56 54 53 52 51 50 49 48 46 45 43 42 41 40 39 38 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.22.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=37 - ORDER BY t1.oid + ORDER BY t1.rowid } } {29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.22.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=37 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29} do_test boundary3-2.22.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=37 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 29 32 54 53 52 33 38} do_test boundary3-2.22.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=37 - ORDER BY t1.oid + ORDER BY t1.rowid } } {29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.22.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=37 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29} do_test boundary3-2.22.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -8388608 ORDER BY t2.a + WHERE t1.rowid >= -8388608 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 45 46 48 49 50 51 52 53 54 56 57 59 60 61 62} do_test boundary3-2.22.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -8388608 ORDER BY t1.a DESC + WHERE t1.rowid >= -8388608 ORDER BY t1.a DESC } } {62 61 60 59 57 56 54 53 52 51 50 49 48 46 45 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.22.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=37 - ORDER BY t1.oid + ORDER BY t1.rowid } } {37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.22.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=37 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37} do_test boundary3-2.22.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=37 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 37 29 32 54 53 52 33 38} do_test boundary3-2.22.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=37 - ORDER BY t1.oid + ORDER BY t1.rowid } } {37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.22.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=37 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37} do_test boundary3-2.22.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -8388608 ORDER BY t2.a + WHERE t1.rowid < -8388608 ORDER BY t2.a } } {1 2 11 21 44 47 55 58 63 64} do_test boundary3-2.22.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -8388608 ORDER BY t1.a DESC + WHERE t1.rowid < -8388608 ORDER BY t1.a DESC } } {64 63 58 55 47 44 21 11 2 1} do_test boundary3-2.22.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=37 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1} do_test boundary3-2.22.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=37 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.22.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=37 ORDER BY x } } {55 2 64 21 44 58 63 47 11 1} do_test boundary3-2.22.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=37 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1} do_test boundary3-2.22.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=37 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.22.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -8388608 ORDER BY t2.a + WHERE t1.rowid <= -8388608 ORDER BY t2.a } } {1 2 11 21 37 44 47 55 58 63 64} do_test boundary3-2.22.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -8388608 ORDER BY t1.a DESC + WHERE t1.rowid <= -8388608 ORDER BY t1.a DESC } } {64 63 58 55 47 44 37 21 11 2 1} do_test boundary3-2.22.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=37 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37} do_test boundary3-2.22.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=37 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.22.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=37 ORDER BY x } } {55 2 64 21 44 58 63 47 11 1 37} do_test boundary3-2.22.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=37 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37} do_test boundary3-2.22.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=37 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.23.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=549755813888 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=549755813888 AND t2.a=t1.a } } {35 0000008000000000} do_test boundary3-2.23.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000008000000000' } } {549755813888 35} do_test boundary3-2.23.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=35 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=35 } } {549755813888 0000008000000000} do_test boundary3-2.23.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 549755813888 ORDER BY t2.a + WHERE t1.rowid > 549755813888 ORDER BY t2.a } } {3 7 10 13 17 19 25 26 27 28 34 43 45 56 57} do_test boundary3-2.23.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 549755813888 ORDER BY t1.a DESC + WHERE t1.rowid > 549755813888 ORDER BY t1.a DESC } } {57 56 45 43 34 28 27 26 25 19 17 13 10 7 3} do_test boundary3-2.23.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=35 - ORDER BY t1.oid + ORDER BY t1.rowid } } {57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.23.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=35 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57} do_test boundary3-2.23.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=35 ORDER BY x } } {57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.23.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=35 - ORDER BY t1.oid + ORDER BY t1.rowid } } {57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.23.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=35 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57} do_test boundary3-2.23.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 549755813888 ORDER BY t2.a + WHERE t1.rowid >= 549755813888 ORDER BY t2.a } } {3 7 10 13 17 19 25 26 27 28 34 35 43 45 56 57} do_test boundary3-2.23.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 549755813888 ORDER BY t1.a DESC + WHERE t1.rowid >= 549755813888 ORDER BY t1.a DESC } } {57 56 45 43 35 34 28 27 26 25 19 17 13 10 7 3} do_test boundary3-2.23.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=35 - ORDER BY t1.oid + ORDER BY t1.rowid } } {35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.23.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=35 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35} do_test boundary3-2.23.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=35 ORDER BY x } } {35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.23.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=35 - ORDER BY t1.oid + ORDER BY t1.rowid } } {35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.23.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=35 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35} do_test boundary3-2.23.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 549755813888 ORDER BY t2.a + WHERE t1.rowid < 549755813888 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 14 15 16 18 20 21 22 23 24 29 30 31 32 33 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.23.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 549755813888 ORDER BY t1.a DESC + WHERE t1.rowid < 549755813888 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 33 32 31 30 29 24 23 22 21 20 18 16 15 14 12 11 9 8 6 5 4 2 1} do_test boundary3-2.23.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=35 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46} do_test boundary3-2.23.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=35 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.23.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=35 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.23.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=35 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46} do_test boundary3-2.23.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=35 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.23.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 549755813888 ORDER BY t2.a + WHERE t1.rowid <= 549755813888 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 14 15 16 18 20 21 22 23 24 29 30 31 32 33 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.23.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 549755813888 ORDER BY t1.a DESC + WHERE t1.rowid <= 549755813888 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 33 32 31 30 29 24 23 22 21 20 18 16 15 14 12 11 9 8 6 5 4 2 1} do_test boundary3-2.23.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=35 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35} do_test boundary3-2.23.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=35 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.23.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=35 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.23.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=35 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35} do_test boundary3-2.23.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=35 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.24.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=8388607 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=8388607 AND t2.a=t1.a } } {18 00000000007fffff} do_test boundary3-2.24.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='00000000007fffff' } } {8388607 18} do_test boundary3-2.24.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=18 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=18 } } {8388607 00000000007fffff} do_test boundary3-2.24.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 8388607 ORDER BY t2.a + WHERE t1.rowid > 8388607 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 17 19 20 22 24 25 26 27 28 34 35 36 39 40 43 45 46 51 56 57} do_test boundary3-2.24.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 8388607 ORDER BY t1.a DESC + WHERE t1.rowid > 8388607 ORDER BY t1.a DESC } } {57 56 51 46 45 43 40 39 36 35 34 28 27 26 25 24 22 20 19 17 14 13 12 10 9 7 6 3} do_test boundary3-2.24.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=18 - ORDER BY t1.oid + ORDER BY t1.rowid } } {24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.24.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=18 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24} do_test boundary3-2.24.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=18 ORDER BY x } } {24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.24.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=18 - ORDER BY t1.oid + ORDER BY t1.rowid } } {24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.24.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=18 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24} do_test boundary3-2.24.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 8388607 ORDER BY t2.a + WHERE t1.rowid >= 8388607 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 17 18 19 20 22 24 25 26 27 28 34 35 36 39 40 43 45 46 51 56 57} do_test boundary3-2.24.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 8388607 ORDER BY t1.a DESC + WHERE t1.rowid >= 8388607 ORDER BY t1.a DESC } } {57 56 51 46 45 43 40 39 36 35 34 28 27 26 25 24 22 20 19 18 17 14 13 12 10 9 7 6 3} do_test boundary3-2.24.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=18 - ORDER BY t1.oid + ORDER BY t1.rowid } } {18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.24.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=18 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18} do_test boundary3-2.24.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=18 ORDER BY x } } {18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.24.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=18 - ORDER BY t1.oid + ORDER BY t1.rowid } } {18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.24.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=18 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18} do_test boundary3-2.24.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 8388607 ORDER BY t2.a + WHERE t1.rowid < 8388607 ORDER BY t2.a } } {1 2 4 5 8 11 15 16 21 23 29 30 31 32 33 37 38 41 42 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.24.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 8388607 ORDER BY t1.a DESC + WHERE t1.rowid < 8388607 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 42 41 38 37 33 32 31 30 29 23 21 16 15 11 8 5 4 2 1} do_test boundary3-2.24.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=18 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42} do_test boundary3-2.24.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=18 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.24.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=18 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.24.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=18 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42} do_test boundary3-2.24.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=18 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.24.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 8388607 ORDER BY t2.a + WHERE t1.rowid <= 8388607 ORDER BY t2.a } } {1 2 4 5 8 11 15 16 18 21 23 29 30 31 32 33 37 38 41 42 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.24.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 8388607 ORDER BY t1.a DESC + WHERE t1.rowid <= 8388607 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 42 41 38 37 33 32 31 30 29 23 21 18 16 15 11 8 5 4 2 1} do_test boundary3-2.24.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=18 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18} do_test boundary3-2.24.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=18 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.24.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=18 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.24.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=18 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18} do_test boundary3-2.24.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=18 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.25.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=-3 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=-3 AND t2.a=t1.a } } {52 fffffffffffffffd} do_test boundary3-2.25.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='fffffffffffffffd' } } {-3 52} do_test boundary3-2.25.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=52 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=52 } } {-3 fffffffffffffffd} do_test boundary3-2.25.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -3 ORDER BY t2.a + WHERE t1.rowid > -3 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 33 34 35 36 38 39 40 41 42 43 45 46 48 49 50 51 56 57 59 60 61 62} do_test boundary3-2.25.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -3 ORDER BY t1.a DESC + WHERE t1.rowid > -3 ORDER BY t1.a DESC } } {62 61 60 59 57 56 51 50 49 48 46 45 43 42 41 40 39 38 36 35 34 33 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.25.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=52 - ORDER BY t1.oid + ORDER BY t1.rowid } } {33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.25.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=52 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33} do_test boundary3-2.25.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=52 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 33 38} do_test boundary3-2.25.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=52 - ORDER BY t1.oid + ORDER BY t1.rowid } } {33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.25.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=52 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33} do_test boundary3-2.25.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -3 ORDER BY t2.a + WHERE t1.rowid >= -3 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 33 34 35 36 38 39 40 41 42 43 45 46 48 49 50 51 52 56 57 59 60 61 62} do_test boundary3-2.25.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -3 ORDER BY t1.a DESC + WHERE t1.rowid >= -3 ORDER BY t1.a DESC } } {62 61 60 59 57 56 52 51 50 49 48 46 45 43 42 41 40 39 38 36 35 34 33 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.25.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=52 - ORDER BY t1.oid + ORDER BY t1.rowid } } {52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.25.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=52 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52} do_test boundary3-2.25.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=52 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 52 33 38} do_test boundary3-2.25.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=52 - ORDER BY t1.oid + ORDER BY t1.rowid } } {52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.25.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=52 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52} do_test boundary3-2.25.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -3 ORDER BY t2.a + WHERE t1.rowid < -3 ORDER BY t2.a } } {1 2 11 21 29 32 37 44 47 53 54 55 58 63 64} do_test boundary3-2.25.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -3 ORDER BY t1.a DESC + WHERE t1.rowid < -3 ORDER BY t1.a DESC } } {64 63 58 55 54 53 47 44 37 32 29 21 11 2 1} do_test boundary3-2.25.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=52 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53} do_test boundary3-2.25.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=52 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.25.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=52 ORDER BY x } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53} do_test boundary3-2.25.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=52 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53} do_test boundary3-2.25.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=52 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.25.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -3 ORDER BY t2.a + WHERE t1.rowid <= -3 ORDER BY t2.a } } {1 2 11 21 29 32 37 44 47 52 53 54 55 58 63 64} do_test boundary3-2.25.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -3 ORDER BY t1.a DESC + WHERE t1.rowid <= -3 ORDER BY t1.a DESC } } {64 63 58 55 54 53 52 47 44 37 32 29 21 11 2 1} do_test boundary3-2.25.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=52 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52} do_test boundary3-2.25.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=52 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.25.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=52 ORDER BY x } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52} do_test boundary3-2.25.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=52 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52} do_test boundary3-2.25.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=52 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.26.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=0 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=0 AND t2.a=t1.a } } {59 0000000000000000} do_test boundary3-2.26.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000000000000' } } {0 59} do_test boundary3-2.26.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=59 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=59 } } {0 0000000000000000} do_test boundary3-2.26.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 0 ORDER BY t2.a + WHERE t1.rowid > 0 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 34 35 36 39 40 41 42 43 45 46 48 49 50 51 56 57 60 61 62} do_test boundary3-2.26.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 0 ORDER BY t1.a DESC + WHERE t1.rowid > 0 ORDER BY t1.a DESC } } {62 61 60 57 56 51 50 49 48 46 45 43 42 41 40 39 36 35 34 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.26.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=59 - ORDER BY t1.oid + ORDER BY t1.rowid } } {60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.26.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=59 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60} do_test boundary3-2.26.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=59 ORDER BY x } } {60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.26.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=59 - ORDER BY t1.oid + ORDER BY t1.rowid } } {60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.26.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=59 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60} do_test boundary3-2.26.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 0 ORDER BY t2.a + WHERE t1.rowid >= 0 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 34 35 36 39 40 41 42 43 45 46 48 49 50 51 56 57 59 60 61 62} do_test boundary3-2.26.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 0 ORDER BY t1.a DESC + WHERE t1.rowid >= 0 ORDER BY t1.a DESC } } {62 61 60 59 57 56 51 50 49 48 46 45 43 42 41 40 39 36 35 34 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.26.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=59 - ORDER BY t1.oid + ORDER BY t1.rowid } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.26.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=59 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59} do_test boundary3-2.26.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=59 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.26.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=59 - ORDER BY t1.oid + ORDER BY t1.rowid } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.26.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=59 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59} do_test boundary3-2.26.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 0 ORDER BY t2.a + WHERE t1.rowid < 0 ORDER BY t2.a } } {1 2 11 21 29 32 33 37 38 44 47 52 53 54 55 58 63 64} do_test boundary3-2.26.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 0 ORDER BY t1.a DESC + WHERE t1.rowid < 0 ORDER BY t1.a DESC } } {64 63 58 55 54 53 52 47 44 38 37 33 32 29 21 11 2 1} do_test boundary3-2.26.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=59 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.26.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=59 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.26.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=59 ORDER BY x } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.26.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=59 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.26.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=59 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.26.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 0 ORDER BY t2.a + WHERE t1.rowid <= 0 ORDER BY t2.a } } {1 2 11 21 29 32 33 37 38 44 47 52 53 54 55 58 59 63 64} do_test boundary3-2.26.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 0 ORDER BY t1.a DESC + WHERE t1.rowid <= 0 ORDER BY t1.a DESC } } {64 63 59 58 55 54 53 52 47 44 38 37 33 32 29 21 11 2 1} do_test boundary3-2.26.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=59 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59} do_test boundary3-2.26.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=59 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.26.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=59 ORDER BY x } } {59 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.26.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=59 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59} do_test boundary3-2.26.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=59 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.27.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=-1 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=-1 AND t2.a=t1.a } } {38 ffffffffffffffff} do_test boundary3-2.27.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='ffffffffffffffff' } } {-1 38} do_test boundary3-2.27.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=38 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=38 } } {-1 ffffffffffffffff} do_test boundary3-2.27.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -1 ORDER BY t2.a + WHERE t1.rowid > -1 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 34 35 36 39 40 41 42 43 45 46 48 49 50 51 56 57 59 60 61 62} do_test boundary3-2.27.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -1 ORDER BY t1.a DESC + WHERE t1.rowid > -1 ORDER BY t1.a DESC } } {62 61 60 59 57 56 51 50 49 48 46 45 43 42 41 40 39 36 35 34 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.27.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=38 - ORDER BY t1.oid + ORDER BY t1.rowid } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.27.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=38 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59} do_test boundary3-2.27.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=38 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.27.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=38 - ORDER BY t1.oid + ORDER BY t1.rowid } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.27.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=38 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59} do_test boundary3-2.27.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -1 ORDER BY t2.a + WHERE t1.rowid >= -1 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 34 35 36 38 39 40 41 42 43 45 46 48 49 50 51 56 57 59 60 61 62} do_test boundary3-2.27.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -1 ORDER BY t1.a DESC + WHERE t1.rowid >= -1 ORDER BY t1.a DESC } } {62 61 60 59 57 56 51 50 49 48 46 45 43 42 41 40 39 38 36 35 34 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.27.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=38 - ORDER BY t1.oid + ORDER BY t1.rowid } } {38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.27.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=38 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38} do_test boundary3-2.27.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=38 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 38} do_test boundary3-2.27.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=38 - ORDER BY t1.oid + ORDER BY t1.rowid } } {38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.27.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=38 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38} do_test boundary3-2.27.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -1 ORDER BY t2.a + WHERE t1.rowid < -1 ORDER BY t2.a } } {1 2 11 21 29 32 33 37 44 47 52 53 54 55 58 63 64} do_test boundary3-2.27.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -1 ORDER BY t1.a DESC + WHERE t1.rowid < -1 ORDER BY t1.a DESC } } {64 63 58 55 54 53 52 47 44 37 33 32 29 21 11 2 1} do_test boundary3-2.27.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=38 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33} do_test boundary3-2.27.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=38 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.27.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=38 ORDER BY x } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33} do_test boundary3-2.27.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=38 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33} do_test boundary3-2.27.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=38 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.27.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -1 ORDER BY t2.a + WHERE t1.rowid <= -1 ORDER BY t2.a } } {1 2 11 21 29 32 33 37 38 44 47 52 53 54 55 58 63 64} do_test boundary3-2.27.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -1 ORDER BY t1.a DESC + WHERE t1.rowid <= -1 ORDER BY t1.a DESC } } {64 63 58 55 54 53 52 47 44 38 37 33 32 29 21 11 2 1} do_test boundary3-2.27.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=38 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.27.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=38 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.27.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=38 ORDER BY x } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.27.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=38 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.27.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=38 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.28.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=-2 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=-2 AND t2.a=t1.a } } {33 fffffffffffffffe} do_test boundary3-2.28.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='fffffffffffffffe' } } {-2 33} do_test boundary3-2.28.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=33 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=33 } } {-2 fffffffffffffffe} do_test boundary3-2.28.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -2 ORDER BY t2.a + WHERE t1.rowid > -2 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 34 35 36 38 39 40 41 42 43 45 46 48 49 50 51 56 57 59 60 61 62} do_test boundary3-2.28.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -2 ORDER BY t1.a DESC + WHERE t1.rowid > -2 ORDER BY t1.a DESC } } {62 61 60 59 57 56 51 50 49 48 46 45 43 42 41 40 39 38 36 35 34 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.28.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=33 - ORDER BY t1.oid + ORDER BY t1.rowid } } {38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.28.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=33 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38} do_test boundary3-2.28.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=33 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 38} do_test boundary3-2.28.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=33 - ORDER BY t1.oid + ORDER BY t1.rowid } } {38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.28.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=33 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38} do_test boundary3-2.28.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -2 ORDER BY t2.a + WHERE t1.rowid >= -2 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 33 34 35 36 38 39 40 41 42 43 45 46 48 49 50 51 56 57 59 60 61 62} do_test boundary3-2.28.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -2 ORDER BY t1.a DESC + WHERE t1.rowid >= -2 ORDER BY t1.a DESC } } {62 61 60 59 57 56 51 50 49 48 46 45 43 42 41 40 39 38 36 35 34 33 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.28.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=33 - ORDER BY t1.oid + ORDER BY t1.rowid } } {33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.28.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=33 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33} do_test boundary3-2.28.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=33 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 33 38} do_test boundary3-2.28.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=33 - ORDER BY t1.oid + ORDER BY t1.rowid } } {33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.28.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=33 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33} do_test boundary3-2.28.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -2 ORDER BY t2.a + WHERE t1.rowid < -2 ORDER BY t2.a } } {1 2 11 21 29 32 37 44 47 52 53 54 55 58 63 64} do_test boundary3-2.28.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -2 ORDER BY t1.a DESC + WHERE t1.rowid < -2 ORDER BY t1.a DESC } } {64 63 58 55 54 53 52 47 44 37 32 29 21 11 2 1} do_test boundary3-2.28.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=33 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52} do_test boundary3-2.28.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=33 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.28.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=33 ORDER BY x } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52} do_test boundary3-2.28.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=33 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52} do_test boundary3-2.28.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=33 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.28.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -2 ORDER BY t2.a + WHERE t1.rowid <= -2 ORDER BY t2.a } } {1 2 11 21 29 32 33 37 44 47 52 53 54 55 58 63 64} do_test boundary3-2.28.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -2 ORDER BY t1.a DESC + WHERE t1.rowid <= -2 ORDER BY t1.a DESC } } {64 63 58 55 54 53 52 47 44 37 33 32 29 21 11 2 1} do_test boundary3-2.28.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=33 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33} do_test boundary3-2.28.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=33 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.28.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=33 ORDER BY x } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33} do_test boundary3-2.28.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=33 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33} do_test boundary3-2.28.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=33 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.29.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=2097152 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=2097152 AND t2.a=t1.a } } {42 0000000000200000} do_test boundary3-2.29.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000000200000' } } {2097152 42} do_test boundary3-2.29.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=42 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=42 } } {2097152 0000000000200000} do_test boundary3-2.29.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 2097152 ORDER BY t2.a + WHERE t1.rowid > 2097152 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 17 18 19 20 22 24 25 26 27 28 34 35 36 39 40 43 45 46 51 56 57} do_test boundary3-2.29.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 2097152 ORDER BY t1.a DESC + WHERE t1.rowid > 2097152 ORDER BY t1.a DESC } } {57 56 51 46 45 43 40 39 36 35 34 28 27 26 25 24 22 20 19 18 17 14 13 12 10 9 7 6 3} do_test boundary3-2.29.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=42 - ORDER BY t1.oid + ORDER BY t1.rowid } } {18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.29.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=42 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18} do_test boundary3-2.29.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=42 ORDER BY x } } {18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.29.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=42 - ORDER BY t1.oid + ORDER BY t1.rowid } } {18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.29.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=42 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18} do_test boundary3-2.29.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 2097152 ORDER BY t2.a + WHERE t1.rowid >= 2097152 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 17 18 19 20 22 24 25 26 27 28 34 35 36 39 40 42 43 45 46 51 56 57} do_test boundary3-2.29.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 2097152 ORDER BY t1.a DESC + WHERE t1.rowid >= 2097152 ORDER BY t1.a DESC } } {57 56 51 46 45 43 42 40 39 36 35 34 28 27 26 25 24 22 20 19 18 17 14 13 12 10 9 7 6 3} do_test boundary3-2.29.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=42 - ORDER BY t1.oid + ORDER BY t1.rowid } } {42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.29.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=42 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42} do_test boundary3-2.29.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=42 ORDER BY x } } {42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.29.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=42 - ORDER BY t1.oid + ORDER BY t1.rowid } } {42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.29.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=42 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42} do_test boundary3-2.29.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 2097152 ORDER BY t2.a + WHERE t1.rowid < 2097152 ORDER BY t2.a } } {1 2 4 5 8 11 15 16 21 23 29 30 31 32 33 37 38 41 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.29.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 2097152 ORDER BY t1.a DESC + WHERE t1.rowid < 2097152 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 41 38 37 33 32 31 30 29 23 21 16 15 11 8 5 4 2 1} do_test boundary3-2.29.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=42 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15} do_test boundary3-2.29.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=42 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.29.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=42 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.29.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=42 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15} do_test boundary3-2.29.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=42 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.29.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 2097152 ORDER BY t2.a + WHERE t1.rowid <= 2097152 ORDER BY t2.a } } {1 2 4 5 8 11 15 16 21 23 29 30 31 32 33 37 38 41 42 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.29.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 2097152 ORDER BY t1.a DESC + WHERE t1.rowid <= 2097152 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 42 41 38 37 33 32 31 30 29 23 21 16 15 11 8 5 4 2 1} do_test boundary3-2.29.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=42 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42} do_test boundary3-2.29.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=42 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.29.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=42 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.29.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=42 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42} do_test boundary3-2.29.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=42 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.30.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=128 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=128 AND t2.a=t1.a } } {49 0000000000000080} do_test boundary3-2.30.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000000000080' } } {128 49} do_test boundary3-2.30.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=49 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=49 } } {128 0000000000000080} do_test boundary3-2.30.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 128 ORDER BY t2.a + WHERE t1.rowid > 128 ORDER BY t2.a } } {3 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 34 35 36 39 40 42 43 45 46 48 50 51 56 57 61 62} do_test boundary3-2.30.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 128 ORDER BY t1.a DESC + WHERE t1.rowid > 128 ORDER BY t1.a DESC } } {62 61 57 56 51 50 48 46 45 43 42 40 39 36 35 34 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 3} do_test boundary3-2.30.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=49 - ORDER BY t1.oid + ORDER BY t1.rowid } } {30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.30.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=49 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30} do_test boundary3-2.30.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=49 ORDER BY x } } {30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.30.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=49 - ORDER BY t1.oid + ORDER BY t1.rowid } } {30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.30.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=49 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30} do_test boundary3-2.30.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 128 ORDER BY t2.a + WHERE t1.rowid >= 128 ORDER BY t2.a } } {3 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 34 35 36 39 40 42 43 45 46 48 49 50 51 56 57 61 62} do_test boundary3-2.30.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 128 ORDER BY t1.a DESC + WHERE t1.rowid >= 128 ORDER BY t1.a DESC } } {62 61 57 56 51 50 49 48 46 45 43 42 40 39 36 35 34 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 3} do_test boundary3-2.30.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=49 - ORDER BY t1.oid + ORDER BY t1.rowid } } {49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.30.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=49 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49} do_test boundary3-2.30.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=49 ORDER BY x } } {49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.30.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=49 - ORDER BY t1.oid + ORDER BY t1.rowid } } {49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.30.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=49 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49} do_test boundary3-2.30.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 128 ORDER BY t2.a + WHERE t1.rowid < 128 ORDER BY t2.a } } {1 2 4 5 11 21 29 31 32 33 37 38 41 44 47 52 53 54 55 58 59 60 63 64} do_test boundary3-2.30.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 128 ORDER BY t1.a DESC + WHERE t1.rowid < 128 ORDER BY t1.a DESC } } {64 63 60 59 58 55 54 53 52 47 44 41 38 37 33 32 31 29 21 11 5 4 2 1} do_test boundary3-2.30.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=49 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4} do_test boundary3-2.30.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=49 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.30.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=49 ORDER BY x } } {59 60 41 5 31 4 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.30.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=49 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4} do_test boundary3-2.30.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=49 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.30.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 128 ORDER BY t2.a + WHERE t1.rowid <= 128 ORDER BY t2.a } } {1 2 4 5 11 21 29 31 32 33 37 38 41 44 47 49 52 53 54 55 58 59 60 63 64} do_test boundary3-2.30.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 128 ORDER BY t1.a DESC + WHERE t1.rowid <= 128 ORDER BY t1.a DESC } } {64 63 60 59 58 55 54 53 52 49 47 44 41 38 37 33 32 31 29 21 11 5 4 2 1} do_test boundary3-2.30.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=49 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49} do_test boundary3-2.30.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=49 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.30.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=49 ORDER BY x } } {59 60 41 5 31 4 49 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.30.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=49 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49} do_test boundary3-2.30.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=49 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.31.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=255 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=255 AND t2.a=t1.a } } {30 00000000000000ff} do_test boundary3-2.31.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='00000000000000ff' } } {255 30} do_test boundary3-2.31.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=30 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=30 } } {255 00000000000000ff} do_test boundary3-2.31.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 255 ORDER BY t2.a + WHERE t1.rowid > 255 ORDER BY t2.a } } {3 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 34 35 36 39 40 42 43 45 46 48 50 51 56 57 61 62} do_test boundary3-2.31.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 255 ORDER BY t1.a DESC + WHERE t1.rowid > 255 ORDER BY t1.a DESC } } {62 61 57 56 51 50 48 46 45 43 42 40 39 36 35 34 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 3} do_test boundary3-2.31.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=30 - ORDER BY t1.oid + ORDER BY t1.rowid } } {61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.31.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=30 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61} do_test boundary3-2.31.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=30 ORDER BY x } } {61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.31.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=30 - ORDER BY t1.oid + ORDER BY t1.rowid } } {61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.31.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=30 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61} do_test boundary3-2.31.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 255 ORDER BY t2.a + WHERE t1.rowid >= 255 ORDER BY t2.a } } {3 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 34 35 36 39 40 42 43 45 46 48 50 51 56 57 61 62} do_test boundary3-2.31.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 255 ORDER BY t1.a DESC + WHERE t1.rowid >= 255 ORDER BY t1.a DESC } } {62 61 57 56 51 50 48 46 45 43 42 40 39 36 35 34 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 3} do_test boundary3-2.31.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=30 - ORDER BY t1.oid + ORDER BY t1.rowid } } {30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.31.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=30 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30} do_test boundary3-2.31.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=30 ORDER BY x } } {30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.31.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=30 - ORDER BY t1.oid + ORDER BY t1.rowid } } {30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.31.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=30 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30} do_test boundary3-2.31.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 255 ORDER BY t2.a + WHERE t1.rowid < 255 ORDER BY t2.a } } {1 2 4 5 11 21 29 31 32 33 37 38 41 44 47 49 52 53 54 55 58 59 60 63 64} do_test boundary3-2.31.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 255 ORDER BY t1.a DESC + WHERE t1.rowid < 255 ORDER BY t1.a DESC } } {64 63 60 59 58 55 54 53 52 49 47 44 41 38 37 33 32 31 29 21 11 5 4 2 1} do_test boundary3-2.31.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=30 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49} do_test boundary3-2.31.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=30 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.31.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=30 ORDER BY x } } {59 60 41 5 31 4 49 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.31.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=30 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49} do_test boundary3-2.31.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=30 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.31.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 255 ORDER BY t2.a + WHERE t1.rowid <= 255 ORDER BY t2.a } } {1 2 4 5 11 21 29 30 31 32 33 37 38 41 44 47 49 52 53 54 55 58 59 60 63 64} do_test boundary3-2.31.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 255 ORDER BY t1.a DESC + WHERE t1.rowid <= 255 ORDER BY t1.a DESC } } {64 63 60 59 58 55 54 53 52 49 47 44 41 38 37 33 32 31 30 29 21 11 5 4 2 1} do_test boundary3-2.31.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=30 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30} do_test boundary3-2.31.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=30 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.31.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=30 ORDER BY x } } {59 60 41 5 31 4 49 30 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.31.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=30 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30} do_test boundary3-2.31.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=30 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.32.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=-2147483648 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=-2147483648 AND t2.a=t1.a } } {11 ffffffff80000000} do_test boundary3-2.32.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='ffffffff80000000' } } {-2147483648 11} do_test boundary3-2.32.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=11 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=11 } } {-2147483648 ffffffff80000000} do_test boundary3-2.32.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -2147483648 ORDER BY t2.a + WHERE t1.rowid > -2147483648 ORDER BY t2.a } } {1 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 45 46 48 49 50 51 52 53 54 56 57 59 60 61 62} do_test boundary3-2.32.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -2147483648 ORDER BY t1.a DESC + WHERE t1.rowid > -2147483648 ORDER BY t1.a DESC } } {62 61 60 59 57 56 54 53 52 51 50 49 48 46 45 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3 1} do_test boundary3-2.32.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=11 - ORDER BY t1.oid + ORDER BY t1.rowid } } {1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.32.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=11 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1} do_test boundary3-2.32.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=11 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 1 37 29 32 54 53 52 33 38} do_test boundary3-2.32.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=11 - ORDER BY t1.oid + ORDER BY t1.rowid } } {1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.32.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=11 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1} do_test boundary3-2.32.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -2147483648 ORDER BY t2.a + WHERE t1.rowid >= -2147483648 ORDER BY t2.a } } {1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 45 46 48 49 50 51 52 53 54 56 57 59 60 61 62} do_test boundary3-2.32.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -2147483648 ORDER BY t1.a DESC + WHERE t1.rowid >= -2147483648 ORDER BY t1.a DESC } } {62 61 60 59 57 56 54 53 52 51 50 49 48 46 45 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 1} do_test boundary3-2.32.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=11 - ORDER BY t1.oid + ORDER BY t1.rowid } } {11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.32.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=11 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11} do_test boundary3-2.32.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=11 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.32.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=11 - ORDER BY t1.oid + ORDER BY t1.rowid } } {11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.32.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=11 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11} do_test boundary3-2.32.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -2147483648 ORDER BY t2.a + WHERE t1.rowid < -2147483648 ORDER BY t2.a } } {2 21 44 47 55 58 63 64} do_test boundary3-2.32.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -2147483648 ORDER BY t1.a DESC + WHERE t1.rowid < -2147483648 ORDER BY t1.a DESC } } {64 63 58 55 47 44 21 2} do_test boundary3-2.32.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=11 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47} do_test boundary3-2.32.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=11 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {47 63 58 44 21 64 2 55} do_test boundary3-2.32.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=11 ORDER BY x } } {55 2 64 21 44 58 63 47} do_test boundary3-2.32.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=11 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47} do_test boundary3-2.32.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=11 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {47 63 58 44 21 64 2 55} do_test boundary3-2.32.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -2147483648 ORDER BY t2.a + WHERE t1.rowid <= -2147483648 ORDER BY t2.a } } {2 11 21 44 47 55 58 63 64} do_test boundary3-2.32.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -2147483648 ORDER BY t1.a DESC + WHERE t1.rowid <= -2147483648 ORDER BY t1.a DESC } } {64 63 58 55 47 44 21 11 2} do_test boundary3-2.32.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=11 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11} do_test boundary3-2.32.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=11 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {11 47 63 58 44 21 64 2 55} do_test boundary3-2.32.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=11 ORDER BY x } } {55 2 64 21 44 58 63 47 11} do_test boundary3-2.32.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=11 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11} do_test boundary3-2.32.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=11 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {11 47 63 58 44 21 64 2 55} do_test boundary3-2.33.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=34359738367 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=34359738367 AND t2.a=t1.a } } {39 00000007ffffffff} do_test boundary3-2.33.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='00000007ffffffff' } } {34359738367 39} do_test boundary3-2.33.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=39 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=39 } } {34359738367 00000007ffffffff} do_test boundary3-2.33.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 34359738367 ORDER BY t2.a + WHERE t1.rowid > 34359738367 ORDER BY t2.a } } {3 7 10 13 17 19 22 25 26 27 28 34 35 43 45 46 56 57} do_test boundary3-2.33.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 34359738367 ORDER BY t1.a DESC + WHERE t1.rowid > 34359738367 ORDER BY t1.a DESC } } {57 56 46 45 43 35 34 28 27 26 25 22 19 17 13 10 7 3} do_test boundary3-2.33.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=39 - ORDER BY t1.oid + ORDER BY t1.rowid } } {22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.33.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=39 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22} do_test boundary3-2.33.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=39 ORDER BY x } } {22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.33.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=39 - ORDER BY t1.oid + ORDER BY t1.rowid } } {22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.33.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=39 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22} do_test boundary3-2.33.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 34359738367 ORDER BY t2.a + WHERE t1.rowid >= 34359738367 ORDER BY t2.a } } {3 7 10 13 17 19 22 25 26 27 28 34 35 39 43 45 46 56 57} do_test boundary3-2.33.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 34359738367 ORDER BY t1.a DESC + WHERE t1.rowid >= 34359738367 ORDER BY t1.a DESC } } {57 56 46 45 43 39 35 34 28 27 26 25 22 19 17 13 10 7 3} do_test boundary3-2.33.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=39 - ORDER BY t1.oid + ORDER BY t1.rowid } } {39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.33.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=39 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39} do_test boundary3-2.33.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=39 ORDER BY x } } {39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.33.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=39 - ORDER BY t1.oid + ORDER BY t1.rowid } } {39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.33.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=39 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39} do_test boundary3-2.33.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 34359738367 ORDER BY t2.a + WHERE t1.rowid < 34359738367 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 14 15 16 18 20 21 23 24 29 30 31 32 33 36 37 38 40 41 42 44 47 48 49 50 51 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.33.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 34359738367 ORDER BY t1.a DESC + WHERE t1.rowid < 34359738367 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 51 50 49 48 47 44 42 41 40 38 37 36 33 32 31 30 29 24 23 21 20 18 16 15 14 12 11 9 8 6 5 4 2 1} do_test boundary3-2.33.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=39 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36} do_test boundary3-2.33.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=39 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.33.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=39 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.33.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=39 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36} do_test boundary3-2.33.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=39 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.33.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 34359738367 ORDER BY t2.a + WHERE t1.rowid <= 34359738367 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 14 15 16 18 20 21 23 24 29 30 31 32 33 36 37 38 39 40 41 42 44 47 48 49 50 51 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.33.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 34359738367 ORDER BY t1.a DESC + WHERE t1.rowid <= 34359738367 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 51 50 49 48 47 44 42 41 40 39 38 37 36 33 32 31 30 29 24 23 21 20 18 16 15 14 12 11 9 8 6 5 4 2 1} do_test boundary3-2.33.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=39 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39} do_test boundary3-2.33.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=39 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.33.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=39 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.33.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=39 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39} do_test boundary3-2.33.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=39 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.34.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=-549755813889 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=-549755813889 AND t2.a=t1.a } } {58 ffffff7fffffffff} do_test boundary3-2.34.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='ffffff7fffffffff' } } {-549755813889 58} do_test boundary3-2.34.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=58 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=58 } } {-549755813889 ffffff7fffffffff} do_test boundary3-2.34.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -549755813889 ORDER BY t2.a + WHERE t1.rowid > -549755813889 ORDER BY t2.a } } {1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 45 46 47 48 49 50 51 52 53 54 56 57 59 60 61 62 63} do_test boundary3-2.34.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -549755813889 ORDER BY t1.a DESC + WHERE t1.rowid > -549755813889 ORDER BY t1.a DESC } } {63 62 61 60 59 57 56 54 53 52 51 50 49 48 47 46 45 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 1} do_test boundary3-2.34.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=58 - ORDER BY t1.oid + ORDER BY t1.rowid } } {63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.34.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=58 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63} do_test boundary3-2.34.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=58 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.34.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=58 - ORDER BY t1.oid + ORDER BY t1.rowid } } {63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.34.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=58 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63} do_test boundary3-2.34.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -549755813889 ORDER BY t2.a + WHERE t1.rowid >= -549755813889 ORDER BY t2.a } } {1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 45 46 47 48 49 50 51 52 53 54 56 57 58 59 60 61 62 63} do_test boundary3-2.34.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -549755813889 ORDER BY t1.a DESC + WHERE t1.rowid >= -549755813889 ORDER BY t1.a DESC } } {63 62 61 60 59 58 57 56 54 53 52 51 50 49 48 47 46 45 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 1} do_test boundary3-2.34.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=58 - ORDER BY t1.oid + ORDER BY t1.rowid } } {58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.34.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=58 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58} do_test boundary3-2.34.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=58 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.34.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=58 - ORDER BY t1.oid + ORDER BY t1.rowid } } {58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.34.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=58 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58} do_test boundary3-2.34.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -549755813889 ORDER BY t2.a + WHERE t1.rowid < -549755813889 ORDER BY t2.a } } {2 21 44 55 64} do_test boundary3-2.34.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -549755813889 ORDER BY t1.a DESC + WHERE t1.rowid < -549755813889 ORDER BY t1.a DESC } } {64 55 44 21 2} do_test boundary3-2.34.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=58 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44} do_test boundary3-2.34.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=58 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {44 21 64 2 55} do_test boundary3-2.34.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=58 ORDER BY x } } {55 2 64 21 44} do_test boundary3-2.34.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=58 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44} do_test boundary3-2.34.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=58 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {44 21 64 2 55} do_test boundary3-2.34.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -549755813889 ORDER BY t2.a + WHERE t1.rowid <= -549755813889 ORDER BY t2.a } } {2 21 44 55 58 64} do_test boundary3-2.34.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -549755813889 ORDER BY t1.a DESC + WHERE t1.rowid <= -549755813889 ORDER BY t1.a DESC } } {64 58 55 44 21 2} do_test boundary3-2.34.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=58 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58} do_test boundary3-2.34.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=58 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {58 44 21 64 2 55} do_test boundary3-2.34.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=58 ORDER BY x } } {55 2 64 21 44 58} do_test boundary3-2.34.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=58 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58} do_test boundary3-2.34.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=58 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {58 44 21 64 2 55} do_test boundary3-2.35.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=-32768 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=-32768 AND t2.a=t1.a } } {32 ffffffffffff8000} do_test boundary3-2.35.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='ffffffffffff8000' } } {-32768 32} do_test boundary3-2.35.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=32 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=32 } } {-32768 ffffffffffff8000} do_test boundary3-2.35.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -32768 ORDER BY t2.a + WHERE t1.rowid > -32768 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 33 34 35 36 38 39 40 41 42 43 45 46 48 49 50 51 52 53 54 56 57 59 60 61 62} do_test boundary3-2.35.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -32768 ORDER BY t1.a DESC + WHERE t1.rowid > -32768 ORDER BY t1.a DESC } } {62 61 60 59 57 56 54 53 52 51 50 49 48 46 45 43 42 41 40 39 38 36 35 34 33 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.35.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=32 - ORDER BY t1.oid + ORDER BY t1.rowid } } {54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.35.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=32 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54} do_test boundary3-2.35.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=32 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 54 53 52 33 38} do_test boundary3-2.35.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=32 - ORDER BY t1.oid + ORDER BY t1.rowid } } {54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.35.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=32 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54} do_test boundary3-2.35.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -32768 ORDER BY t2.a + WHERE t1.rowid >= -32768 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 32 33 34 35 36 38 39 40 41 42 43 45 46 48 49 50 51 52 53 54 56 57 59 60 61 62} do_test boundary3-2.35.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -32768 ORDER BY t1.a DESC + WHERE t1.rowid >= -32768 ORDER BY t1.a DESC } } {62 61 60 59 57 56 54 53 52 51 50 49 48 46 45 43 42 41 40 39 38 36 35 34 33 32 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.35.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=32 - ORDER BY t1.oid + ORDER BY t1.rowid } } {32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.35.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=32 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32} do_test boundary3-2.35.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=32 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 32 54 53 52 33 38} do_test boundary3-2.35.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=32 - ORDER BY t1.oid + ORDER BY t1.rowid } } {32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.35.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=32 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32} do_test boundary3-2.35.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -32768 ORDER BY t2.a + WHERE t1.rowid < -32768 ORDER BY t2.a } } {1 2 11 21 29 37 44 47 55 58 63 64} do_test boundary3-2.35.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -32768 ORDER BY t1.a DESC + WHERE t1.rowid < -32768 ORDER BY t1.a DESC } } {64 63 58 55 47 44 37 29 21 11 2 1} do_test boundary3-2.35.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=32 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29} do_test boundary3-2.35.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=32 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.35.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=32 ORDER BY x } } {55 2 64 21 44 58 63 47 11 1 37 29} do_test boundary3-2.35.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=32 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29} do_test boundary3-2.35.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=32 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.35.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -32768 ORDER BY t2.a + WHERE t1.rowid <= -32768 ORDER BY t2.a } } {1 2 11 21 29 32 37 44 47 55 58 63 64} do_test boundary3-2.35.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -32768 ORDER BY t1.a DESC + WHERE t1.rowid <= -32768 ORDER BY t1.a DESC } } {64 63 58 55 47 44 37 32 29 21 11 2 1} do_test boundary3-2.35.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=32 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32} do_test boundary3-2.35.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=32 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.35.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=32 ORDER BY x } } {55 2 64 21 44 58 63 47 11 1 37 29 32} do_test boundary3-2.35.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=32 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32} do_test boundary3-2.35.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=32 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.36.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=2147483647 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=2147483647 AND t2.a=t1.a } } {20 000000007fffffff} do_test boundary3-2.36.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='000000007fffffff' } } {2147483647 20} do_test boundary3-2.36.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=20 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=20 } } {2147483647 000000007fffffff} do_test boundary3-2.36.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 2147483647 ORDER BY t2.a + WHERE t1.rowid > 2147483647 ORDER BY t2.a } } {3 7 10 13 14 17 19 22 25 26 27 28 34 35 36 39 43 45 46 51 56 57} do_test boundary3-2.36.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 2147483647 ORDER BY t1.a DESC + WHERE t1.rowid > 2147483647 ORDER BY t1.a DESC } } {57 56 51 46 45 43 39 36 35 34 28 27 26 25 22 19 17 14 13 10 7 3} do_test boundary3-2.36.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=20 - ORDER BY t1.oid + ORDER BY t1.rowid } } {51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.36.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=20 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51} do_test boundary3-2.36.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=20 ORDER BY x } } {51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.36.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=20 - ORDER BY t1.oid + ORDER BY t1.rowid } } {51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.36.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=20 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51} do_test boundary3-2.36.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 2147483647 ORDER BY t2.a + WHERE t1.rowid >= 2147483647 ORDER BY t2.a } } {3 7 10 13 14 17 19 20 22 25 26 27 28 34 35 36 39 43 45 46 51 56 57} do_test boundary3-2.36.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 2147483647 ORDER BY t1.a DESC + WHERE t1.rowid >= 2147483647 ORDER BY t1.a DESC } } {57 56 51 46 45 43 39 36 35 34 28 27 26 25 22 20 19 17 14 13 10 7 3} do_test boundary3-2.36.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=20 - ORDER BY t1.oid + ORDER BY t1.rowid } } {20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.36.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=20 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20} do_test boundary3-2.36.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=20 ORDER BY x } } {20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.36.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=20 - ORDER BY t1.oid + ORDER BY t1.rowid } } {20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.36.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=20 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20} do_test boundary3-2.36.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 2147483647 ORDER BY t2.a + WHERE t1.rowid < 2147483647 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 15 16 18 21 23 24 29 30 31 32 33 37 38 40 41 42 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.36.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 2147483647 ORDER BY t1.a DESC + WHERE t1.rowid < 2147483647 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 42 41 40 38 37 33 32 31 30 29 24 23 21 18 16 15 12 11 9 8 6 5 4 2 1} do_test boundary3-2.36.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=20 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40} do_test boundary3-2.36.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=20 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.36.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=20 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.36.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=20 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40} do_test boundary3-2.36.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=20 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.36.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 2147483647 ORDER BY t2.a + WHERE t1.rowid <= 2147483647 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 15 16 18 20 21 23 24 29 30 31 32 33 37 38 40 41 42 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.36.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 2147483647 ORDER BY t1.a DESC + WHERE t1.rowid <= 2147483647 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 42 41 40 38 37 33 32 31 30 29 24 23 21 20 18 16 15 12 11 9 8 6 5 4 2 1} do_test boundary3-2.36.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=20 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20} do_test boundary3-2.36.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=20 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.36.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=20 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.36.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=20 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20} do_test boundary3-2.36.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=20 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.37.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=-129 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=-129 AND t2.a=t1.a } } {54 ffffffffffffff7f} do_test boundary3-2.37.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='ffffffffffffff7f' } } {-129 54} do_test boundary3-2.37.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=54 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=54 } } {-129 ffffffffffffff7f} do_test boundary3-2.37.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -129 ORDER BY t2.a + WHERE t1.rowid > -129 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 33 34 35 36 38 39 40 41 42 43 45 46 48 49 50 51 52 53 56 57 59 60 61 62} do_test boundary3-2.37.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -129 ORDER BY t1.a DESC + WHERE t1.rowid > -129 ORDER BY t1.a DESC } } {62 61 60 59 57 56 53 52 51 50 49 48 46 45 43 42 41 40 39 38 36 35 34 33 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.37.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=54 - ORDER BY t1.oid + ORDER BY t1.rowid } } {53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.37.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=54 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53} do_test boundary3-2.37.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=54 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 53 52 33 38} do_test boundary3-2.37.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=54 - ORDER BY t1.oid + ORDER BY t1.rowid } } {53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.37.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=54 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53} do_test boundary3-2.37.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -129 ORDER BY t2.a + WHERE t1.rowid >= -129 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 33 34 35 36 38 39 40 41 42 43 45 46 48 49 50 51 52 53 54 56 57 59 60 61 62} do_test boundary3-2.37.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -129 ORDER BY t1.a DESC + WHERE t1.rowid >= -129 ORDER BY t1.a DESC } } {62 61 60 59 57 56 54 53 52 51 50 49 48 46 45 43 42 41 40 39 38 36 35 34 33 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.37.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=54 - ORDER BY t1.oid + ORDER BY t1.rowid } } {54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.37.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=54 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54} do_test boundary3-2.37.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=54 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 54 53 52 33 38} do_test boundary3-2.37.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=54 - ORDER BY t1.oid + ORDER BY t1.rowid } } {54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.37.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=54 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54} do_test boundary3-2.37.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -129 ORDER BY t2.a + WHERE t1.rowid < -129 ORDER BY t2.a } } {1 2 11 21 29 32 37 44 47 55 58 63 64} do_test boundary3-2.37.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -129 ORDER BY t1.a DESC + WHERE t1.rowid < -129 ORDER BY t1.a DESC } } {64 63 58 55 47 44 37 32 29 21 11 2 1} do_test boundary3-2.37.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=54 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32} do_test boundary3-2.37.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=54 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.37.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=54 ORDER BY x } } {55 2 64 21 44 58 63 47 11 1 37 29 32} do_test boundary3-2.37.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=54 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32} do_test boundary3-2.37.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=54 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.37.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -129 ORDER BY t2.a + WHERE t1.rowid <= -129 ORDER BY t2.a } } {1 2 11 21 29 32 37 44 47 54 55 58 63 64} do_test boundary3-2.37.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -129 ORDER BY t1.a DESC + WHERE t1.rowid <= -129 ORDER BY t1.a DESC } } {64 63 58 55 54 47 44 37 32 29 21 11 2 1} do_test boundary3-2.37.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=54 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54} do_test boundary3-2.37.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=54 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.37.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=54 ORDER BY x } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54} do_test boundary3-2.37.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=54 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54} do_test boundary3-2.37.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=54 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.38.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=-128 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=-128 AND t2.a=t1.a } } {53 ffffffffffffff80} do_test boundary3-2.38.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='ffffffffffffff80' } } {-128 53} do_test boundary3-2.38.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=53 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=53 } } {-128 ffffffffffffff80} do_test boundary3-2.38.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -128 ORDER BY t2.a + WHERE t1.rowid > -128 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 33 34 35 36 38 39 40 41 42 43 45 46 48 49 50 51 52 56 57 59 60 61 62} do_test boundary3-2.38.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -128 ORDER BY t1.a DESC + WHERE t1.rowid > -128 ORDER BY t1.a DESC } } {62 61 60 59 57 56 52 51 50 49 48 46 45 43 42 41 40 39 38 36 35 34 33 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.38.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=53 - ORDER BY t1.oid + ORDER BY t1.rowid } } {52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.38.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=53 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52} do_test boundary3-2.38.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=53 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 52 33 38} do_test boundary3-2.38.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=53 - ORDER BY t1.oid + ORDER BY t1.rowid } } {52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.38.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=53 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52} do_test boundary3-2.38.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -128 ORDER BY t2.a + WHERE t1.rowid >= -128 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 33 34 35 36 38 39 40 41 42 43 45 46 48 49 50 51 52 53 56 57 59 60 61 62} do_test boundary3-2.38.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -128 ORDER BY t1.a DESC + WHERE t1.rowid >= -128 ORDER BY t1.a DESC } } {62 61 60 59 57 56 53 52 51 50 49 48 46 45 43 42 41 40 39 38 36 35 34 33 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.38.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=53 - ORDER BY t1.oid + ORDER BY t1.rowid } } {53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.38.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=53 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53} do_test boundary3-2.38.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=53 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 53 52 33 38} do_test boundary3-2.38.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=53 - ORDER BY t1.oid + ORDER BY t1.rowid } } {53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.38.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=53 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53} do_test boundary3-2.38.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -128 ORDER BY t2.a + WHERE t1.rowid < -128 ORDER BY t2.a } } {1 2 11 21 29 32 37 44 47 54 55 58 63 64} do_test boundary3-2.38.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -128 ORDER BY t1.a DESC + WHERE t1.rowid < -128 ORDER BY t1.a DESC } } {64 63 58 55 54 47 44 37 32 29 21 11 2 1} do_test boundary3-2.38.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=53 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54} do_test boundary3-2.38.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=53 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.38.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=53 ORDER BY x } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54} do_test boundary3-2.38.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=53 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54} do_test boundary3-2.38.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=53 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.38.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -128 ORDER BY t2.a + WHERE t1.rowid <= -128 ORDER BY t2.a } } {1 2 11 21 29 32 37 44 47 53 54 55 58 63 64} do_test boundary3-2.38.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -128 ORDER BY t1.a DESC + WHERE t1.rowid <= -128 ORDER BY t1.a DESC } } {64 63 58 55 54 53 47 44 37 32 29 21 11 2 1} do_test boundary3-2.38.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=53 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53} do_test boundary3-2.38.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=53 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.38.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=53 ORDER BY x } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53} do_test boundary3-2.38.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=53 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53} do_test boundary3-2.38.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=53 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.39.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=72057594037927936 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=72057594037927936 AND t2.a=t1.a } } {28 0100000000000000} do_test boundary3-2.39.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0100000000000000' } } {72057594037927936 28} do_test boundary3-2.39.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=28 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=28 } } {72057594037927936 0100000000000000} do_test boundary3-2.39.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 72057594037927936 ORDER BY t2.a + WHERE t1.rowid > 72057594037927936 ORDER BY t2.a } } {3} do_test boundary3-2.39.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 72057594037927936 ORDER BY t1.a DESC + WHERE t1.rowid > 72057594037927936 ORDER BY t1.a DESC } } {3} do_test boundary3-2.39.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=28 - ORDER BY t1.oid + ORDER BY t1.rowid } } {3} do_test boundary3-2.39.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=28 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3} do_test boundary3-2.39.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=28 ORDER BY x } } {3} do_test boundary3-2.39.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 72057594037927936 ORDER BY t2.a + WHERE t1.rowid >= 72057594037927936 ORDER BY t2.a } } {3 28} do_test boundary3-2.39.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 72057594037927936 ORDER BY t1.a DESC + WHERE t1.rowid >= 72057594037927936 ORDER BY t1.a DESC } } {28 3} do_test boundary3-2.39.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=28 - ORDER BY t1.oid + ORDER BY t1.rowid } } {28 3} do_test boundary3-2.39.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=28 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28} do_test boundary3-2.39.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=28 ORDER BY x } } {28 3} do_test boundary3-2.39.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 72057594037927936 ORDER BY t2.a + WHERE t1.rowid < 72057594037927936 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.39.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 72057594037927936 ORDER BY t1.a DESC + WHERE t1.rowid < 72057594037927936 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 2 1} do_test boundary3-2.39.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=28 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17} do_test boundary3-2.39.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=28 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.39.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=28 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.39.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 72057594037927936 ORDER BY t2.a + WHERE t1.rowid <= 72057594037927936 ORDER BY t2.a } } {1 2 4 5 6 7 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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.39.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 72057594037927936 ORDER BY t1.a DESC + WHERE t1.rowid <= 72057594037927936 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 2 1} do_test boundary3-2.39.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=28 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28} do_test boundary3-2.39.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=28 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.39.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=28 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.40.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=2147483648 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=2147483648 AND t2.a=t1.a } } {51 0000000080000000} do_test boundary3-2.40.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000080000000' } } {2147483648 51} do_test boundary3-2.40.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=51 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=51 } } {2147483648 0000000080000000} do_test boundary3-2.40.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 2147483648 ORDER BY t2.a + WHERE t1.rowid > 2147483648 ORDER BY t2.a } } {3 7 10 13 14 17 19 22 25 26 27 28 34 35 36 39 43 45 46 56 57} do_test boundary3-2.40.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 2147483648 ORDER BY t1.a DESC + WHERE t1.rowid > 2147483648 ORDER BY t1.a DESC } } {57 56 46 45 43 39 36 35 34 28 27 26 25 22 19 17 14 13 10 7 3} do_test boundary3-2.40.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=51 - ORDER BY t1.oid + ORDER BY t1.rowid } } {14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.40.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=51 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14} do_test boundary3-2.40.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=51 ORDER BY x } } {14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.40.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=51 - ORDER BY t1.oid + ORDER BY t1.rowid } } {14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.40.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=51 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14} do_test boundary3-2.40.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 2147483648 ORDER BY t2.a + WHERE t1.rowid >= 2147483648 ORDER BY t2.a } } {3 7 10 13 14 17 19 22 25 26 27 28 34 35 36 39 43 45 46 51 56 57} do_test boundary3-2.40.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 2147483648 ORDER BY t1.a DESC + WHERE t1.rowid >= 2147483648 ORDER BY t1.a DESC } } {57 56 51 46 45 43 39 36 35 34 28 27 26 25 22 19 17 14 13 10 7 3} do_test boundary3-2.40.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=51 - ORDER BY t1.oid + ORDER BY t1.rowid } } {51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.40.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=51 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51} do_test boundary3-2.40.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=51 ORDER BY x } } {51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.40.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=51 - ORDER BY t1.oid + ORDER BY t1.rowid } } {51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.40.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=51 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51} do_test boundary3-2.40.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 2147483648 ORDER BY t2.a + WHERE t1.rowid < 2147483648 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 15 16 18 20 21 23 24 29 30 31 32 33 37 38 40 41 42 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.40.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 2147483648 ORDER BY t1.a DESC + WHERE t1.rowid < 2147483648 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 42 41 40 38 37 33 32 31 30 29 24 23 21 20 18 16 15 12 11 9 8 6 5 4 2 1} do_test boundary3-2.40.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=51 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20} do_test boundary3-2.40.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=51 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.40.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=51 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.40.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=51 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20} do_test boundary3-2.40.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=51 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.40.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 2147483648 ORDER BY t2.a + WHERE t1.rowid <= 2147483648 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 15 16 18 20 21 23 24 29 30 31 32 33 37 38 40 41 42 44 47 48 49 50 51 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.40.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 2147483648 ORDER BY t1.a DESC + WHERE t1.rowid <= 2147483648 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 51 50 49 48 47 44 42 41 40 38 37 33 32 31 30 29 24 23 21 20 18 16 15 12 11 9 8 6 5 4 2 1} do_test boundary3-2.40.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=51 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51} do_test boundary3-2.40.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=51 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.40.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=51 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.40.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=51 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51} do_test boundary3-2.40.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=51 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.41.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=549755813887 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=549755813887 AND t2.a=t1.a } } {46 0000007fffffffff} do_test boundary3-2.41.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000007fffffffff' } } {549755813887 46} do_test boundary3-2.41.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=46 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=46 } } {549755813887 0000007fffffffff} do_test boundary3-2.41.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 549755813887 ORDER BY t2.a + WHERE t1.rowid > 549755813887 ORDER BY t2.a } } {3 7 10 13 17 19 25 26 27 28 34 35 43 45 56 57} do_test boundary3-2.41.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 549755813887 ORDER BY t1.a DESC + WHERE t1.rowid > 549755813887 ORDER BY t1.a DESC } } {57 56 45 43 35 34 28 27 26 25 19 17 13 10 7 3} do_test boundary3-2.41.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=46 - ORDER BY t1.oid + ORDER BY t1.rowid } } {35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.41.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=46 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35} do_test boundary3-2.41.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=46 ORDER BY x } } {35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.41.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=46 - ORDER BY t1.oid + ORDER BY t1.rowid } } {35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.41.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=46 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35} do_test boundary3-2.41.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 549755813887 ORDER BY t2.a + WHERE t1.rowid >= 549755813887 ORDER BY t2.a } } {3 7 10 13 17 19 25 26 27 28 34 35 43 45 46 56 57} do_test boundary3-2.41.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 549755813887 ORDER BY t1.a DESC + WHERE t1.rowid >= 549755813887 ORDER BY t1.a DESC } } {57 56 46 45 43 35 34 28 27 26 25 19 17 13 10 7 3} do_test boundary3-2.41.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=46 - ORDER BY t1.oid + ORDER BY t1.rowid } } {46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.41.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=46 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46} do_test boundary3-2.41.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=46 ORDER BY x } } {46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.41.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=46 - ORDER BY t1.oid + ORDER BY t1.rowid } } {46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.41.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=46 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46} do_test boundary3-2.41.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 549755813887 ORDER BY t2.a + WHERE t1.rowid < 549755813887 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 14 15 16 18 20 21 22 23 24 29 30 31 32 33 36 37 38 39 40 41 42 44 47 48 49 50 51 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.41.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 549755813887 ORDER BY t1.a DESC + WHERE t1.rowid < 549755813887 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 51 50 49 48 47 44 42 41 40 39 38 37 36 33 32 31 30 29 24 23 22 21 20 18 16 15 14 12 11 9 8 6 5 4 2 1} do_test boundary3-2.41.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=46 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22} do_test boundary3-2.41.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=46 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.41.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=46 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.41.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=46 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22} do_test boundary3-2.41.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=46 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.41.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 549755813887 ORDER BY t2.a + WHERE t1.rowid <= 549755813887 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 14 15 16 18 20 21 22 23 24 29 30 31 32 33 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.41.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 549755813887 ORDER BY t1.a DESC + WHERE t1.rowid <= 549755813887 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 33 32 31 30 29 24 23 22 21 20 18 16 15 14 12 11 9 8 6 5 4 2 1} do_test boundary3-2.41.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=46 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46} do_test boundary3-2.41.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=46 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.41.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=46 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.41.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=46 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46} do_test boundary3-2.41.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=46 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.42.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=-549755813888 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=-549755813888 AND t2.a=t1.a } } {63 ffffff8000000000} do_test boundary3-2.42.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='ffffff8000000000' } } {-549755813888 63} do_test boundary3-2.42.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=63 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=63 } } {-549755813888 ffffff8000000000} do_test boundary3-2.42.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -549755813888 ORDER BY t2.a + WHERE t1.rowid > -549755813888 ORDER BY t2.a } } {1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 45 46 47 48 49 50 51 52 53 54 56 57 59 60 61 62} do_test boundary3-2.42.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -549755813888 ORDER BY t1.a DESC + WHERE t1.rowid > -549755813888 ORDER BY t1.a DESC } } {62 61 60 59 57 56 54 53 52 51 50 49 48 47 46 45 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 1} do_test boundary3-2.42.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=63 - ORDER BY t1.oid + ORDER BY t1.rowid } } {47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.42.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=63 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47} do_test boundary3-2.42.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=63 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.42.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=63 - ORDER BY t1.oid + ORDER BY t1.rowid } } {47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.42.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=63 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47} do_test boundary3-2.42.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -549755813888 ORDER BY t2.a + WHERE t1.rowid >= -549755813888 ORDER BY t2.a } } {1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 45 46 47 48 49 50 51 52 53 54 56 57 59 60 61 62 63} do_test boundary3-2.42.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -549755813888 ORDER BY t1.a DESC + WHERE t1.rowid >= -549755813888 ORDER BY t1.a DESC } } {63 62 61 60 59 57 56 54 53 52 51 50 49 48 47 46 45 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 1} do_test boundary3-2.42.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=63 - ORDER BY t1.oid + ORDER BY t1.rowid } } {63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.42.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=63 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63} do_test boundary3-2.42.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=63 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.42.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=63 - ORDER BY t1.oid + ORDER BY t1.rowid } } {63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.42.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=63 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63} do_test boundary3-2.42.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -549755813888 ORDER BY t2.a + WHERE t1.rowid < -549755813888 ORDER BY t2.a } } {2 21 44 55 58 64} do_test boundary3-2.42.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -549755813888 ORDER BY t1.a DESC + WHERE t1.rowid < -549755813888 ORDER BY t1.a DESC } } {64 58 55 44 21 2} do_test boundary3-2.42.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=63 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58} do_test boundary3-2.42.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=63 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {58 44 21 64 2 55} do_test boundary3-2.42.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=63 ORDER BY x } } {55 2 64 21 44 58} do_test boundary3-2.42.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=63 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58} do_test boundary3-2.42.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=63 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {58 44 21 64 2 55} do_test boundary3-2.42.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -549755813888 ORDER BY t2.a + WHERE t1.rowid <= -549755813888 ORDER BY t2.a } } {2 21 44 55 58 63 64} do_test boundary3-2.42.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -549755813888 ORDER BY t1.a DESC + WHERE t1.rowid <= -549755813888 ORDER BY t1.a DESC } } {64 63 58 55 44 21 2} do_test boundary3-2.42.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=63 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63} do_test boundary3-2.42.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=63 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {63 58 44 21 64 2 55} do_test boundary3-2.42.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=63 ORDER BY x } } {55 2 64 21 44 58 63} do_test boundary3-2.42.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=63 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63} do_test boundary3-2.42.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=63 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {63 58 44 21 64 2 55} do_test boundary3-2.43.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=281474976710655 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=281474976710655 AND t2.a=t1.a } } {10 0000ffffffffffff} do_test boundary3-2.43.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000ffffffffffff' } } {281474976710655 10} do_test boundary3-2.43.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=10 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=10 } } {281474976710655 0000ffffffffffff} do_test boundary3-2.43.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 281474976710655 ORDER BY t2.a + WHERE t1.rowid > 281474976710655 ORDER BY t2.a } } {3 13 17 26 27 28 43 45} do_test boundary3-2.43.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 281474976710655 ORDER BY t1.a DESC + WHERE t1.rowid > 281474976710655 ORDER BY t1.a DESC } } {45 43 28 27 26 17 13 3} do_test boundary3-2.43.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=10 - ORDER BY t1.oid + ORDER BY t1.rowid } } {26 13 43 27 45 17 28 3} do_test boundary3-2.43.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=10 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26} do_test boundary3-2.43.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=10 ORDER BY x } } {26 13 43 27 45 17 28 3} do_test boundary3-2.43.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 281474976710655 ORDER BY t2.a + WHERE t1.rowid >= 281474976710655 ORDER BY t2.a } } {3 10 13 17 26 27 28 43 45} do_test boundary3-2.43.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 281474976710655 ORDER BY t1.a DESC + WHERE t1.rowid >= 281474976710655 ORDER BY t1.a DESC } } {45 43 28 27 26 17 13 10 3} do_test boundary3-2.43.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=10 - ORDER BY t1.oid + ORDER BY t1.rowid } } {10 26 13 43 27 45 17 28 3} do_test boundary3-2.43.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=10 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10} do_test boundary3-2.43.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=10 ORDER BY x } } {10 26 13 43 27 45 17 28 3} do_test boundary3-2.43.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 281474976710655 ORDER BY t2.a + WHERE t1.rowid < 281474976710655 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 11 12 14 15 16 18 19 20 21 22 23 24 25 29 30 31 32 33 34 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.43.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 281474976710655 ORDER BY t1.a DESC + WHERE t1.rowid < 281474976710655 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 34 33 32 31 30 29 25 24 23 22 21 20 19 18 16 15 14 12 11 9 8 7 6 5 4 2 1} do_test boundary3-2.43.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=10 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34} do_test boundary3-2.43.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=10 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.43.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=10 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.43.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 281474976710655 ORDER BY t2.a + WHERE t1.rowid <= 281474976710655 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 10 11 12 14 15 16 18 19 20 21 22 23 24 25 29 30 31 32 33 34 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.43.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 281474976710655 ORDER BY t1.a DESC + WHERE t1.rowid <= 281474976710655 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 34 33 32 31 30 29 25 24 23 22 21 20 19 18 16 15 14 12 11 10 9 8 7 6 5 4 2 1} do_test boundary3-2.43.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=10 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10} do_test boundary3-2.43.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=10 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.43.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=10 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.44.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=4398046511103 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=4398046511103 AND t2.a=t1.a } } {7 000003ffffffffff} do_test boundary3-2.44.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='000003ffffffffff' } } {4398046511103 7} do_test boundary3-2.44.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=7 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=7 } } {4398046511103 000003ffffffffff} do_test boundary3-2.44.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 4398046511103 ORDER BY t2.a + WHERE t1.rowid > 4398046511103 ORDER BY t2.a } } {3 10 13 17 25 26 27 28 34 43 45 56} do_test boundary3-2.44.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 4398046511103 ORDER BY t1.a DESC + WHERE t1.rowid > 4398046511103 ORDER BY t1.a DESC } } {56 45 43 34 28 27 26 25 17 13 10 3} do_test boundary3-2.44.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=7 - ORDER BY t1.oid + ORDER BY t1.rowid } } {56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.44.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=7 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56} do_test boundary3-2.44.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=7 ORDER BY x } } {56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.44.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=7 - ORDER BY t1.oid + ORDER BY t1.rowid } } {56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.44.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=7 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56} do_test boundary3-2.44.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 4398046511103 ORDER BY t2.a + WHERE t1.rowid >= 4398046511103 ORDER BY t2.a } } {3 7 10 13 17 25 26 27 28 34 43 45 56} do_test boundary3-2.44.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 4398046511103 ORDER BY t1.a DESC + WHERE t1.rowid >= 4398046511103 ORDER BY t1.a DESC } } {56 45 43 34 28 27 26 25 17 13 10 7 3} do_test boundary3-2.44.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=7 - ORDER BY t1.oid + ORDER BY t1.rowid } } {7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.44.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=7 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7} do_test boundary3-2.44.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=7 ORDER BY x } } {7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.44.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=7 - ORDER BY t1.oid + ORDER BY t1.rowid } } {7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.44.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=7 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7} do_test boundary3-2.44.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 4398046511103 ORDER BY t2.a + WHERE t1.rowid < 4398046511103 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 14 15 16 18 19 20 21 22 23 24 29 30 31 32 33 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 57 58 59 60 61 62 63 64} do_test boundary3-2.44.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 4398046511103 ORDER BY t1.a DESC + WHERE t1.rowid < 4398046511103 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 33 32 31 30 29 24 23 22 21 20 19 18 16 15 14 12 11 9 8 6 5 4 2 1} do_test boundary3-2.44.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=7 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19} do_test boundary3-2.44.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=7 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.44.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=7 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.44.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=7 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19} do_test boundary3-2.44.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=7 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.44.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 4398046511103 ORDER BY t2.a + WHERE t1.rowid <= 4398046511103 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 11 12 14 15 16 18 19 20 21 22 23 24 29 30 31 32 33 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 57 58 59 60 61 62 63 64} do_test boundary3-2.44.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 4398046511103 ORDER BY t1.a DESC + WHERE t1.rowid <= 4398046511103 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 33 32 31 30 29 24 23 22 21 20 19 18 16 15 14 12 11 9 8 7 6 5 4 2 1} do_test boundary3-2.44.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=7 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7} do_test boundary3-2.44.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=7 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.44.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=7 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.44.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=7 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7} do_test boundary3-2.44.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=7 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.45.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=268435455 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=268435455 AND t2.a=t1.a } } {12 000000000fffffff} do_test boundary3-2.45.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='000000000fffffff' } } {268435455 12} do_test boundary3-2.45.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=12 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=12 } } {268435455 000000000fffffff} do_test boundary3-2.45.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 268435455 ORDER BY t2.a + WHERE t1.rowid > 268435455 ORDER BY t2.a } } {3 7 10 13 14 17 19 20 22 25 26 27 28 34 35 36 39 40 43 45 46 51 56 57} do_test boundary3-2.45.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 268435455 ORDER BY t1.a DESC + WHERE t1.rowid > 268435455 ORDER BY t1.a DESC } } {57 56 51 46 45 43 40 39 36 35 34 28 27 26 25 22 20 19 17 14 13 10 7 3} do_test boundary3-2.45.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=12 - ORDER BY t1.oid + ORDER BY t1.rowid } } {40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.45.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=12 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40} do_test boundary3-2.45.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=12 ORDER BY x } } {40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.45.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=12 - ORDER BY t1.oid + ORDER BY t1.rowid } } {40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.45.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=12 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40} do_test boundary3-2.45.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 268435455 ORDER BY t2.a + WHERE t1.rowid >= 268435455 ORDER BY t2.a } } {3 7 10 12 13 14 17 19 20 22 25 26 27 28 34 35 36 39 40 43 45 46 51 56 57} do_test boundary3-2.45.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 268435455 ORDER BY t1.a DESC + WHERE t1.rowid >= 268435455 ORDER BY t1.a DESC } } {57 56 51 46 45 43 40 39 36 35 34 28 27 26 25 22 20 19 17 14 13 12 10 7 3} do_test boundary3-2.45.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=12 - ORDER BY t1.oid + ORDER BY t1.rowid } } {12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.45.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=12 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12} do_test boundary3-2.45.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=12 ORDER BY x } } {12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.45.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=12 - ORDER BY t1.oid + ORDER BY t1.rowid } } {12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.45.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=12 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12} do_test boundary3-2.45.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 268435455 ORDER BY t2.a + WHERE t1.rowid < 268435455 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 15 16 18 21 23 24 29 30 31 32 33 37 38 41 42 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.45.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 268435455 ORDER BY t1.a DESC + WHERE t1.rowid < 268435455 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 42 41 38 37 33 32 31 30 29 24 23 21 18 16 15 11 9 8 6 5 4 2 1} do_test boundary3-2.45.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=12 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6} do_test boundary3-2.45.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=12 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.45.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=12 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.45.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=12 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6} do_test boundary3-2.45.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=12 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.45.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 268435455 ORDER BY t2.a + WHERE t1.rowid <= 268435455 ORDER BY t2.a } } {1 2 4 5 6 8 9 11 12 15 16 18 21 23 24 29 30 31 32 33 37 38 41 42 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.45.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 268435455 ORDER BY t1.a DESC + WHERE t1.rowid <= 268435455 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 42 41 38 37 33 32 31 30 29 24 23 21 18 16 15 12 11 9 8 6 5 4 2 1} do_test boundary3-2.45.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=12 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12} do_test boundary3-2.45.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=12 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.45.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=12 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.45.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=12 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12} do_test boundary3-2.45.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=12 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.46.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=-9223372036854775808 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=-9223372036854775808 AND t2.a=t1.a } } {55 8000000000000000} do_test boundary3-2.46.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='8000000000000000' } } {-9223372036854775808 55} do_test boundary3-2.46.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=55 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=55 } } {-9223372036854775808 8000000000000000} do_test boundary3-2.46.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -9223372036854775808 ORDER BY t2.a + WHERE t1.rowid > -9223372036854775808 ORDER BY t2.a } } {1 2 3 4 5 6 7 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 42 43 44 45 46 47 48 49 50 51 52 53 54 56 57 58 59 60 61 62 63 64} do_test boundary3-2.46.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -9223372036854775808 ORDER BY t1.a DESC + WHERE t1.rowid > -9223372036854775808 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1} do_test boundary3-2.46.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=55 - ORDER BY t1.oid + ORDER BY t1.rowid } } {2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.46.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=55 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2} do_test boundary3-2.46.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=55 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.46.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -9223372036854775808 ORDER BY t2.a + WHERE t1.rowid >= -9223372036854775808 ORDER BY t2.a } } {1 2 3 4 5 6 7 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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.46.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -9223372036854775808 ORDER BY t1.a DESC + WHERE t1.rowid >= -9223372036854775808 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1} do_test boundary3-2.46.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=55 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.46.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=55 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.46.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=55 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.46.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -9223372036854775808 ORDER BY t2.a + WHERE t1.rowid < -9223372036854775808 ORDER BY t2.a } } {} do_test boundary3-2.46.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -9223372036854775808 ORDER BY t1.a DESC + WHERE t1.rowid < -9223372036854775808 ORDER BY t1.a DESC } } {} do_test boundary3-2.46.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=55 - ORDER BY t1.oid + ORDER BY t1.rowid } } {} do_test boundary3-2.46.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=55 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {} do_test boundary3-2.46.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=55 ORDER BY x } } {} do_test boundary3-2.46.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -9223372036854775808 ORDER BY t2.a + WHERE t1.rowid <= -9223372036854775808 ORDER BY t2.a } } {55} do_test boundary3-2.46.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -9223372036854775808 ORDER BY t1.a DESC + WHERE t1.rowid <= -9223372036854775808 ORDER BY t1.a DESC } } {55} do_test boundary3-2.46.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=55 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55} do_test boundary3-2.46.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=55 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {55} do_test boundary3-2.46.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=55 ORDER BY x } } {55} do_test boundary3-2.47.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=562949953421312 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=562949953421312 AND t2.a=t1.a } } {43 0002000000000000} do_test boundary3-2.47.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0002000000000000' } } {562949953421312 43} do_test boundary3-2.47.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=43 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=43 } } {562949953421312 0002000000000000} do_test boundary3-2.47.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 562949953421312 ORDER BY t2.a + WHERE t1.rowid > 562949953421312 ORDER BY t2.a } } {3 17 27 28 45} do_test boundary3-2.47.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 562949953421312 ORDER BY t1.a DESC + WHERE t1.rowid > 562949953421312 ORDER BY t1.a DESC } } {45 28 27 17 3} do_test boundary3-2.47.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=43 - ORDER BY t1.oid + ORDER BY t1.rowid } } {27 45 17 28 3} do_test boundary3-2.47.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=43 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27} do_test boundary3-2.47.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=43 ORDER BY x } } {27 45 17 28 3} do_test boundary3-2.47.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 562949953421312 ORDER BY t2.a + WHERE t1.rowid >= 562949953421312 ORDER BY t2.a } } {3 17 27 28 43 45} do_test boundary3-2.47.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 562949953421312 ORDER BY t1.a DESC + WHERE t1.rowid >= 562949953421312 ORDER BY t1.a DESC } } {45 43 28 27 17 3} do_test boundary3-2.47.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=43 - ORDER BY t1.oid + ORDER BY t1.rowid } } {43 27 45 17 28 3} do_test boundary3-2.47.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=43 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43} do_test boundary3-2.47.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=43 ORDER BY x } } {43 27 45 17 28 3} do_test boundary3-2.47.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 562949953421312 ORDER BY t2.a + WHERE t1.rowid < 562949953421312 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 10 11 12 13 14 15 16 18 19 20 21 22 23 24 25 26 29 30 31 32 33 34 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.47.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 562949953421312 ORDER BY t1.a DESC + WHERE t1.rowid < 562949953421312 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 34 33 32 31 30 29 26 25 24 23 22 21 20 19 18 16 15 14 13 12 11 10 9 8 7 6 5 4 2 1} do_test boundary3-2.47.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=43 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13} do_test boundary3-2.47.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=43 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.47.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=43 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.47.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 562949953421312 ORDER BY t2.a + WHERE t1.rowid <= 562949953421312 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 10 11 12 13 14 15 16 18 19 20 21 22 23 24 25 26 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.47.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 562949953421312 ORDER BY t1.a DESC + WHERE t1.rowid <= 562949953421312 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 26 25 24 23 22 21 20 19 18 16 15 14 13 12 11 10 9 8 7 6 5 4 2 1} do_test boundary3-2.47.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=43 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43} do_test boundary3-2.47.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=43 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.47.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=43 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.48.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=-8388609 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=-8388609 AND t2.a=t1.a } } {1 ffffffffff7fffff} do_test boundary3-2.48.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='ffffffffff7fffff' } } {-8388609 1} do_test boundary3-2.48.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=1 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=1 } } {-8388609 ffffffffff7fffff} do_test boundary3-2.48.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -8388609 ORDER BY t2.a + WHERE t1.rowid > -8388609 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 45 46 48 49 50 51 52 53 54 56 57 59 60 61 62} do_test boundary3-2.48.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -8388609 ORDER BY t1.a DESC + WHERE t1.rowid > -8388609 ORDER BY t1.a DESC } } {62 61 60 59 57 56 54 53 52 51 50 49 48 46 45 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.48.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=1 - ORDER BY t1.oid + ORDER BY t1.rowid } } {37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.48.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=1 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37} do_test boundary3-2.48.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=1 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 37 29 32 54 53 52 33 38} do_test boundary3-2.48.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=1 - ORDER BY t1.oid + ORDER BY t1.rowid } } {37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.48.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=1 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37} do_test boundary3-2.48.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -8388609 ORDER BY t2.a + WHERE t1.rowid >= -8388609 ORDER BY t2.a } } {1 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 45 46 48 49 50 51 52 53 54 56 57 59 60 61 62} do_test boundary3-2.48.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -8388609 ORDER BY t1.a DESC + WHERE t1.rowid >= -8388609 ORDER BY t1.a DESC } } {62 61 60 59 57 56 54 53 52 51 50 49 48 46 45 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3 1} do_test boundary3-2.48.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=1 - ORDER BY t1.oid + ORDER BY t1.rowid } } {1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.48.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=1 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1} do_test boundary3-2.48.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=1 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 1 37 29 32 54 53 52 33 38} do_test boundary3-2.48.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=1 - ORDER BY t1.oid + ORDER BY t1.rowid } } {1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.48.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=1 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1} do_test boundary3-2.48.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -8388609 ORDER BY t2.a + WHERE t1.rowid < -8388609 ORDER BY t2.a } } {2 11 21 44 47 55 58 63 64} do_test boundary3-2.48.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -8388609 ORDER BY t1.a DESC + WHERE t1.rowid < -8388609 ORDER BY t1.a DESC } } {64 63 58 55 47 44 21 11 2} do_test boundary3-2.48.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=1 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11} do_test boundary3-2.48.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=1 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {11 47 63 58 44 21 64 2 55} do_test boundary3-2.48.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=1 ORDER BY x } } {55 2 64 21 44 58 63 47 11} do_test boundary3-2.48.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=1 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11} do_test boundary3-2.48.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=1 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {11 47 63 58 44 21 64 2 55} do_test boundary3-2.48.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -8388609 ORDER BY t2.a + WHERE t1.rowid <= -8388609 ORDER BY t2.a } } {1 2 11 21 44 47 55 58 63 64} do_test boundary3-2.48.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -8388609 ORDER BY t1.a DESC + WHERE t1.rowid <= -8388609 ORDER BY t1.a DESC } } {64 63 58 55 47 44 21 11 2 1} do_test boundary3-2.48.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=1 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1} do_test boundary3-2.48.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=1 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.48.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=1 ORDER BY x } } {55 2 64 21 44 58 63 47 11 1} do_test boundary3-2.48.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=1 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1} do_test boundary3-2.48.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=1 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.49.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=16777215 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=16777215 AND t2.a=t1.a } } {9 0000000000ffffff} do_test boundary3-2.49.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000000ffffff' } } {16777215 9} do_test boundary3-2.49.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=9 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=9 } } {16777215 0000000000ffffff} do_test boundary3-2.49.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 16777215 ORDER BY t2.a + WHERE t1.rowid > 16777215 ORDER BY t2.a } } {3 6 7 10 12 13 14 17 19 20 22 25 26 27 28 34 35 36 39 40 43 45 46 51 56 57} do_test boundary3-2.49.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 16777215 ORDER BY t1.a DESC + WHERE t1.rowid > 16777215 ORDER BY t1.a DESC } } {57 56 51 46 45 43 40 39 36 35 34 28 27 26 25 22 20 19 17 14 13 12 10 7 6 3} do_test boundary3-2.49.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=9 - ORDER BY t1.oid + ORDER BY t1.rowid } } {6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.49.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=9 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6} do_test boundary3-2.49.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=9 ORDER BY x } } {6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.49.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=9 - ORDER BY t1.oid + ORDER BY t1.rowid } } {6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.49.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=9 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6} do_test boundary3-2.49.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 16777215 ORDER BY t2.a + WHERE t1.rowid >= 16777215 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 17 19 20 22 25 26 27 28 34 35 36 39 40 43 45 46 51 56 57} do_test boundary3-2.49.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 16777215 ORDER BY t1.a DESC + WHERE t1.rowid >= 16777215 ORDER BY t1.a DESC } } {57 56 51 46 45 43 40 39 36 35 34 28 27 26 25 22 20 19 17 14 13 12 10 9 7 6 3} do_test boundary3-2.49.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=9 - ORDER BY t1.oid + ORDER BY t1.rowid } } {9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.49.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=9 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9} do_test boundary3-2.49.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=9 ORDER BY x } } {9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.49.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=9 - ORDER BY t1.oid + ORDER BY t1.rowid } } {9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.49.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=9 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9} do_test boundary3-2.49.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 16777215 ORDER BY t2.a + WHERE t1.rowid < 16777215 ORDER BY t2.a } } {1 2 4 5 8 11 15 16 18 21 23 24 29 30 31 32 33 37 38 41 42 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.49.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 16777215 ORDER BY t1.a DESC + WHERE t1.rowid < 16777215 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 42 41 38 37 33 32 31 30 29 24 23 21 18 16 15 11 8 5 4 2 1} do_test boundary3-2.49.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=9 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24} do_test boundary3-2.49.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=9 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.49.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=9 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.49.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=9 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24} do_test boundary3-2.49.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=9 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.49.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 16777215 ORDER BY t2.a + WHERE t1.rowid <= 16777215 ORDER BY t2.a } } {1 2 4 5 8 9 11 15 16 18 21 23 24 29 30 31 32 33 37 38 41 42 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.49.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 16777215 ORDER BY t1.a DESC + WHERE t1.rowid <= 16777215 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 42 41 38 37 33 32 31 30 29 24 23 21 18 16 15 11 9 8 5 4 2 1} do_test boundary3-2.49.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=9 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9} do_test boundary3-2.49.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=9 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.49.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=9 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.49.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=9 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9} do_test boundary3-2.49.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=9 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.50.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=8388608 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=8388608 AND t2.a=t1.a } } {24 0000000000800000} do_test boundary3-2.50.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000000800000' } } {8388608 24} do_test boundary3-2.50.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=24 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=24 } } {8388608 0000000000800000} do_test boundary3-2.50.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 8388608 ORDER BY t2.a + WHERE t1.rowid > 8388608 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 17 19 20 22 25 26 27 28 34 35 36 39 40 43 45 46 51 56 57} do_test boundary3-2.50.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 8388608 ORDER BY t1.a DESC + WHERE t1.rowid > 8388608 ORDER BY t1.a DESC } } {57 56 51 46 45 43 40 39 36 35 34 28 27 26 25 22 20 19 17 14 13 12 10 9 7 6 3} do_test boundary3-2.50.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=24 - ORDER BY t1.oid + ORDER BY t1.rowid } } {9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.50.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=24 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9} do_test boundary3-2.50.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=24 ORDER BY x } } {9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.50.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=24 - ORDER BY t1.oid + ORDER BY t1.rowid } } {9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.50.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=24 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9} do_test boundary3-2.50.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 8388608 ORDER BY t2.a + WHERE t1.rowid >= 8388608 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 17 19 20 22 24 25 26 27 28 34 35 36 39 40 43 45 46 51 56 57} do_test boundary3-2.50.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 8388608 ORDER BY t1.a DESC + WHERE t1.rowid >= 8388608 ORDER BY t1.a DESC } } {57 56 51 46 45 43 40 39 36 35 34 28 27 26 25 24 22 20 19 17 14 13 12 10 9 7 6 3} do_test boundary3-2.50.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=24 - ORDER BY t1.oid + ORDER BY t1.rowid } } {24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.50.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=24 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24} do_test boundary3-2.50.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=24 ORDER BY x } } {24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.50.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=24 - ORDER BY t1.oid + ORDER BY t1.rowid } } {24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.50.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=24 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24} do_test boundary3-2.50.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 8388608 ORDER BY t2.a + WHERE t1.rowid < 8388608 ORDER BY t2.a } } {1 2 4 5 8 11 15 16 18 21 23 29 30 31 32 33 37 38 41 42 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.50.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 8388608 ORDER BY t1.a DESC + WHERE t1.rowid < 8388608 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 42 41 38 37 33 32 31 30 29 23 21 18 16 15 11 8 5 4 2 1} do_test boundary3-2.50.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=24 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18} do_test boundary3-2.50.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=24 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.50.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=24 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.50.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=24 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18} do_test boundary3-2.50.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=24 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.50.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 8388608 ORDER BY t2.a + WHERE t1.rowid <= 8388608 ORDER BY t2.a } } {1 2 4 5 8 11 15 16 18 21 23 24 29 30 31 32 33 37 38 41 42 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.50.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 8388608 ORDER BY t1.a DESC + WHERE t1.rowid <= 8388608 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 42 41 38 37 33 32 31 30 29 24 23 21 18 16 15 11 8 5 4 2 1} do_test boundary3-2.50.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=24 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24} do_test boundary3-2.50.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=24 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.50.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=24 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.50.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=24 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24} do_test boundary3-2.50.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=24 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.51.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=16383 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=16383 AND t2.a=t1.a } } {8 0000000000003fff} do_test boundary3-2.51.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000000003fff' } } {16383 8} do_test boundary3-2.51.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=8 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=8 } } {16383 0000000000003fff} do_test boundary3-2.51.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 16383 ORDER BY t2.a + WHERE t1.rowid > 16383 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 34 35 36 39 40 42 43 45 46 48 50 51 56 57 62} do_test boundary3-2.51.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 16383 ORDER BY t1.a DESC + WHERE t1.rowid > 16383 ORDER BY t1.a DESC } } {62 57 56 51 50 48 46 45 43 42 40 39 36 35 34 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 7 6 3} do_test boundary3-2.51.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=8 - ORDER BY t1.oid + ORDER BY t1.rowid } } {16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.51.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=8 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16} do_test boundary3-2.51.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=8 ORDER BY x } } {16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.51.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=8 - ORDER BY t1.oid + ORDER BY t1.rowid } } {16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.51.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=8 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16} do_test boundary3-2.51.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 16383 ORDER BY t2.a + WHERE t1.rowid >= 16383 ORDER BY t2.a } } {3 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 34 35 36 39 40 42 43 45 46 48 50 51 56 57 62} do_test boundary3-2.51.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 16383 ORDER BY t1.a DESC + WHERE t1.rowid >= 16383 ORDER BY t1.a DESC } } {62 57 56 51 50 48 46 45 43 42 40 39 36 35 34 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 3} do_test boundary3-2.51.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=8 - ORDER BY t1.oid + ORDER BY t1.rowid } } {8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.51.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=8 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8} do_test boundary3-2.51.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=8 ORDER BY x } } {8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.51.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=8 - ORDER BY t1.oid + ORDER BY t1.rowid } } {8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.51.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=8 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8} do_test boundary3-2.51.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 16383 ORDER BY t2.a + WHERE t1.rowid < 16383 ORDER BY t2.a } } {1 2 4 5 11 21 29 30 31 32 33 37 38 41 44 47 49 52 53 54 55 58 59 60 61 63 64} do_test boundary3-2.51.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 16383 ORDER BY t1.a DESC + WHERE t1.rowid < 16383 ORDER BY t1.a DESC } } {64 63 61 60 59 58 55 54 53 52 49 47 44 41 38 37 33 32 31 30 29 21 11 5 4 2 1} do_test boundary3-2.51.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=8 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61} do_test boundary3-2.51.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=8 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.51.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=8 ORDER BY x } } {59 60 41 5 31 4 49 30 61 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.51.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=8 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61} do_test boundary3-2.51.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=8 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.51.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 16383 ORDER BY t2.a + WHERE t1.rowid <= 16383 ORDER BY t2.a } } {1 2 4 5 8 11 21 29 30 31 32 33 37 38 41 44 47 49 52 53 54 55 58 59 60 61 63 64} do_test boundary3-2.51.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 16383 ORDER BY t1.a DESC + WHERE t1.rowid <= 16383 ORDER BY t1.a DESC } } {64 63 61 60 59 58 55 54 53 52 49 47 44 41 38 37 33 32 31 30 29 21 11 8 5 4 2 1} do_test boundary3-2.51.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=8 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8} do_test boundary3-2.51.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=8 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.51.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=8 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.51.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=8 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8} do_test boundary3-2.51.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=8 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.52.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=140737488355328 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=140737488355328 AND t2.a=t1.a } } {34 0000800000000000} do_test boundary3-2.52.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000800000000000' } } {140737488355328 34} do_test boundary3-2.52.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=34 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=34 } } {140737488355328 0000800000000000} do_test boundary3-2.52.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 140737488355328 ORDER BY t2.a + WHERE t1.rowid > 140737488355328 ORDER BY t2.a } } {3 10 13 17 26 27 28 43 45} do_test boundary3-2.52.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 140737488355328 ORDER BY t1.a DESC + WHERE t1.rowid > 140737488355328 ORDER BY t1.a DESC } } {45 43 28 27 26 17 13 10 3} do_test boundary3-2.52.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=34 - ORDER BY t1.oid + ORDER BY t1.rowid } } {10 26 13 43 27 45 17 28 3} do_test boundary3-2.52.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=34 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10} do_test boundary3-2.52.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=34 ORDER BY x } } {10 26 13 43 27 45 17 28 3} do_test boundary3-2.52.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 140737488355328 ORDER BY t2.a + WHERE t1.rowid >= 140737488355328 ORDER BY t2.a } } {3 10 13 17 26 27 28 34 43 45} do_test boundary3-2.52.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 140737488355328 ORDER BY t1.a DESC + WHERE t1.rowid >= 140737488355328 ORDER BY t1.a DESC } } {45 43 34 28 27 26 17 13 10 3} do_test boundary3-2.52.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=34 - ORDER BY t1.oid + ORDER BY t1.rowid } } {34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.52.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=34 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34} do_test boundary3-2.52.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=34 ORDER BY x } } {34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.52.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 140737488355328 ORDER BY t2.a + WHERE t1.rowid < 140737488355328 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 11 12 14 15 16 18 19 20 21 22 23 24 25 29 30 31 32 33 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.52.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 140737488355328 ORDER BY t1.a DESC + WHERE t1.rowid < 140737488355328 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 33 32 31 30 29 25 24 23 22 21 20 19 18 16 15 14 12 11 9 8 7 6 5 4 2 1} do_test boundary3-2.52.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=34 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25} do_test boundary3-2.52.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=34 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.52.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=34 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.52.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 140737488355328 ORDER BY t2.a + WHERE t1.rowid <= 140737488355328 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 11 12 14 15 16 18 19 20 21 22 23 24 25 29 30 31 32 33 34 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.52.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 140737488355328 ORDER BY t1.a DESC + WHERE t1.rowid <= 140737488355328 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 34 33 32 31 30 29 25 24 23 22 21 20 19 18 16 15 14 12 11 9 8 7 6 5 4 2 1} do_test boundary3-2.52.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=34 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34} do_test boundary3-2.52.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=34 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.52.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=34 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.53.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=2097151 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=2097151 AND t2.a=t1.a } } {15 00000000001fffff} do_test boundary3-2.53.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='00000000001fffff' } } {2097151 15} do_test boundary3-2.53.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=15 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=15 } } {2097151 00000000001fffff} do_test boundary3-2.53.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 2097151 ORDER BY t2.a + WHERE t1.rowid > 2097151 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 17 18 19 20 22 24 25 26 27 28 34 35 36 39 40 42 43 45 46 51 56 57} do_test boundary3-2.53.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 2097151 ORDER BY t1.a DESC + WHERE t1.rowid > 2097151 ORDER BY t1.a DESC } } {57 56 51 46 45 43 42 40 39 36 35 34 28 27 26 25 24 22 20 19 18 17 14 13 12 10 9 7 6 3} do_test boundary3-2.53.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=15 - ORDER BY t1.oid + ORDER BY t1.rowid } } {42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.53.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=15 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42} do_test boundary3-2.53.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=15 ORDER BY x } } {42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.53.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=15 - ORDER BY t1.oid + ORDER BY t1.rowid } } {42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.53.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=15 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42} do_test boundary3-2.53.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 2097151 ORDER BY t2.a + WHERE t1.rowid >= 2097151 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 15 17 18 19 20 22 24 25 26 27 28 34 35 36 39 40 42 43 45 46 51 56 57} do_test boundary3-2.53.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 2097151 ORDER BY t1.a DESC + WHERE t1.rowid >= 2097151 ORDER BY t1.a DESC } } {57 56 51 46 45 43 42 40 39 36 35 34 28 27 26 25 24 22 20 19 18 17 15 14 13 12 10 9 7 6 3} do_test boundary3-2.53.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=15 - ORDER BY t1.oid + ORDER BY t1.rowid } } {15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.53.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=15 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15} do_test boundary3-2.53.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=15 ORDER BY x } } {15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.53.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=15 - ORDER BY t1.oid + ORDER BY t1.rowid } } {15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.53.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=15 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15} do_test boundary3-2.53.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 2097151 ORDER BY t2.a + WHERE t1.rowid < 2097151 ORDER BY t2.a } } {1 2 4 5 8 11 16 21 23 29 30 31 32 33 37 38 41 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.53.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 2097151 ORDER BY t1.a DESC + WHERE t1.rowid < 2097151 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 41 38 37 33 32 31 30 29 23 21 16 11 8 5 4 2 1} do_test boundary3-2.53.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=15 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62} do_test boundary3-2.53.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=15 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.53.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=15 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.53.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=15 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62} do_test boundary3-2.53.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=15 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.53.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 2097151 ORDER BY t2.a + WHERE t1.rowid <= 2097151 ORDER BY t2.a } } {1 2 4 5 8 11 15 16 21 23 29 30 31 32 33 37 38 41 44 47 48 49 50 52 53 54 55 58 59 60 61 62 63 64} do_test boundary3-2.53.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 2097151 ORDER BY t1.a DESC + WHERE t1.rowid <= 2097151 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 55 54 53 52 50 49 48 47 44 41 38 37 33 32 31 30 29 23 21 16 15 11 8 5 4 2 1} do_test boundary3-2.53.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=15 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15} do_test boundary3-2.53.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=15 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.53.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=15 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.53.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=15 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15} do_test boundary3-2.53.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=15 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.54.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=140737488355327 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=140737488355327 AND t2.a=t1.a } } {25 00007fffffffffff} do_test boundary3-2.54.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='00007fffffffffff' } } {140737488355327 25} do_test boundary3-2.54.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=25 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=25 } } {140737488355327 00007fffffffffff} do_test boundary3-2.54.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 140737488355327 ORDER BY t2.a + WHERE t1.rowid > 140737488355327 ORDER BY t2.a } } {3 10 13 17 26 27 28 34 43 45} do_test boundary3-2.54.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 140737488355327 ORDER BY t1.a DESC + WHERE t1.rowid > 140737488355327 ORDER BY t1.a DESC } } {45 43 34 28 27 26 17 13 10 3} do_test boundary3-2.54.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=25 - ORDER BY t1.oid + ORDER BY t1.rowid } } {34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.54.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=25 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34} do_test boundary3-2.54.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=25 ORDER BY x } } {34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.54.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 140737488355327 ORDER BY t2.a + WHERE t1.rowid >= 140737488355327 ORDER BY t2.a } } {3 10 13 17 25 26 27 28 34 43 45} do_test boundary3-2.54.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 140737488355327 ORDER BY t1.a DESC + WHERE t1.rowid >= 140737488355327 ORDER BY t1.a DESC } } {45 43 34 28 27 26 25 17 13 10 3} do_test boundary3-2.54.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=25 - ORDER BY t1.oid + ORDER BY t1.rowid } } {25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.54.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=25 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25} do_test boundary3-2.54.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=25 ORDER BY x } } {25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.54.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 140737488355327 ORDER BY t2.a + WHERE t1.rowid < 140737488355327 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 11 12 14 15 16 18 19 20 21 22 23 24 29 30 31 32 33 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.54.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 140737488355327 ORDER BY t1.a DESC + WHERE t1.rowid < 140737488355327 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 33 32 31 30 29 24 23 22 21 20 19 18 16 15 14 12 11 9 8 7 6 5 4 2 1} do_test boundary3-2.54.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=25 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56} do_test boundary3-2.54.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=25 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.54.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=25 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.54.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 140737488355327 ORDER BY t2.a + WHERE t1.rowid <= 140737488355327 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 11 12 14 15 16 18 19 20 21 22 23 24 25 29 30 31 32 33 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.54.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 140737488355327 ORDER BY t1.a DESC + WHERE t1.rowid <= 140737488355327 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 33 32 31 30 29 25 24 23 22 21 20 19 18 16 15 14 12 11 9 8 7 6 5 4 2 1} do_test boundary3-2.54.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=25 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25} do_test boundary3-2.54.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=25 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.54.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=25 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.55.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=281474976710656 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=281474976710656 AND t2.a=t1.a } } {26 0001000000000000} do_test boundary3-2.55.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0001000000000000' } } {281474976710656 26} do_test boundary3-2.55.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=26 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=26 } } {281474976710656 0001000000000000} do_test boundary3-2.55.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 281474976710656 ORDER BY t2.a + WHERE t1.rowid > 281474976710656 ORDER BY t2.a } } {3 13 17 27 28 43 45} do_test boundary3-2.55.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 281474976710656 ORDER BY t1.a DESC + WHERE t1.rowid > 281474976710656 ORDER BY t1.a DESC } } {45 43 28 27 17 13 3} do_test boundary3-2.55.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=26 - ORDER BY t1.oid + ORDER BY t1.rowid } } {13 43 27 45 17 28 3} do_test boundary3-2.55.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=26 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13} do_test boundary3-2.55.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=26 ORDER BY x } } {13 43 27 45 17 28 3} do_test boundary3-2.55.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 281474976710656 ORDER BY t2.a + WHERE t1.rowid >= 281474976710656 ORDER BY t2.a } } {3 13 17 26 27 28 43 45} do_test boundary3-2.55.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 281474976710656 ORDER BY t1.a DESC + WHERE t1.rowid >= 281474976710656 ORDER BY t1.a DESC } } {45 43 28 27 26 17 13 3} do_test boundary3-2.55.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=26 - ORDER BY t1.oid + ORDER BY t1.rowid } } {26 13 43 27 45 17 28 3} do_test boundary3-2.55.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=26 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26} do_test boundary3-2.55.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=26 ORDER BY x } } {26 13 43 27 45 17 28 3} do_test boundary3-2.55.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 281474976710656 ORDER BY t2.a + WHERE t1.rowid < 281474976710656 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 10 11 12 14 15 16 18 19 20 21 22 23 24 25 29 30 31 32 33 34 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.55.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 281474976710656 ORDER BY t1.a DESC + WHERE t1.rowid < 281474976710656 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 34 33 32 31 30 29 25 24 23 22 21 20 19 18 16 15 14 12 11 10 9 8 7 6 5 4 2 1} do_test boundary3-2.55.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=26 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10} do_test boundary3-2.55.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=26 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.55.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=26 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.55.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 281474976710656 ORDER BY t2.a + WHERE t1.rowid <= 281474976710656 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 10 11 12 14 15 16 18 19 20 21 22 23 24 25 26 29 30 31 32 33 34 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.55.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 281474976710656 ORDER BY t1.a DESC + WHERE t1.rowid <= 281474976710656 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 34 33 32 31 30 29 26 25 24 23 22 21 20 19 18 16 15 14 12 11 10 9 8 7 6 5 4 2 1} do_test boundary3-2.55.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=26 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26} do_test boundary3-2.55.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=26 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.55.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=26 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.56.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=32767 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=32767 AND t2.a=t1.a } } {23 0000000000007fff} do_test boundary3-2.56.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000000007fff' } } {32767 23} do_test boundary3-2.56.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=23 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=23 } } {32767 0000000000007fff} do_test boundary3-2.56.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 32767 ORDER BY t2.a + WHERE t1.rowid > 32767 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 15 17 18 19 20 22 24 25 26 27 28 34 35 36 39 40 42 43 45 46 48 50 51 56 57 62} do_test boundary3-2.56.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 32767 ORDER BY t1.a DESC + WHERE t1.rowid > 32767 ORDER BY t1.a DESC } } {62 57 56 51 50 48 46 45 43 42 40 39 36 35 34 28 27 26 25 24 22 20 19 18 17 15 14 13 12 10 9 7 6 3} do_test boundary3-2.56.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=23 - ORDER BY t1.oid + ORDER BY t1.rowid } } {50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.56.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=23 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50} do_test boundary3-2.56.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=23 ORDER BY x } } {50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.56.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=23 - ORDER BY t1.oid + ORDER BY t1.rowid } } {50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.56.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=23 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50} do_test boundary3-2.56.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 32767 ORDER BY t2.a + WHERE t1.rowid >= 32767 ORDER BY t2.a } } {3 6 7 9 10 12 13 14 15 17 18 19 20 22 23 24 25 26 27 28 34 35 36 39 40 42 43 45 46 48 50 51 56 57 62} do_test boundary3-2.56.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 32767 ORDER BY t1.a DESC + WHERE t1.rowid >= 32767 ORDER BY t1.a DESC } } {62 57 56 51 50 48 46 45 43 42 40 39 36 35 34 28 27 26 25 24 23 22 20 19 18 17 15 14 13 12 10 9 7 6 3} do_test boundary3-2.56.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=23 - ORDER BY t1.oid + ORDER BY t1.rowid } } {23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.56.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=23 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23} do_test boundary3-2.56.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=23 ORDER BY x } } {23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.56.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=23 - ORDER BY t1.oid + ORDER BY t1.rowid } } {23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.56.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=23 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23} do_test boundary3-2.56.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 32767 ORDER BY t2.a + WHERE t1.rowid < 32767 ORDER BY t2.a } } {1 2 4 5 8 11 16 21 29 30 31 32 33 37 38 41 44 47 49 52 53 54 55 58 59 60 61 63 64} do_test boundary3-2.56.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 32767 ORDER BY t1.a DESC + WHERE t1.rowid < 32767 ORDER BY t1.a DESC } } {64 63 61 60 59 58 55 54 53 52 49 47 44 41 38 37 33 32 31 30 29 21 16 11 8 5 4 2 1} do_test boundary3-2.56.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=23 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16} do_test boundary3-2.56.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=23 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.56.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=23 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.56.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=23 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16} do_test boundary3-2.56.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=23 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.56.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 32767 ORDER BY t2.a + WHERE t1.rowid <= 32767 ORDER BY t2.a } } {1 2 4 5 8 11 16 21 23 29 30 31 32 33 37 38 41 44 47 49 52 53 54 55 58 59 60 61 63 64} do_test boundary3-2.56.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 32767 ORDER BY t1.a DESC + WHERE t1.rowid <= 32767 ORDER BY t1.a DESC } } {64 63 61 60 59 58 55 54 53 52 49 47 44 41 38 37 33 32 31 30 29 23 21 16 11 8 5 4 2 1} do_test boundary3-2.56.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=23 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23} do_test boundary3-2.56.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=23 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.56.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=23 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.56.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=23 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23} do_test boundary3-2.56.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=23 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.57.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=127 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=127 AND t2.a=t1.a } } {4 000000000000007f} do_test boundary3-2.57.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='000000000000007f' } } {127 4} do_test boundary3-2.57.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=4 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=4 } } {127 000000000000007f} do_test boundary3-2.57.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 127 ORDER BY t2.a + WHERE t1.rowid > 127 ORDER BY t2.a } } {3 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 34 35 36 39 40 42 43 45 46 48 49 50 51 56 57 61 62} do_test boundary3-2.57.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 127 ORDER BY t1.a DESC + WHERE t1.rowid > 127 ORDER BY t1.a DESC } } {62 61 57 56 51 50 49 48 46 45 43 42 40 39 36 35 34 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 3} do_test boundary3-2.57.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=4 - ORDER BY t1.oid + ORDER BY t1.rowid } } {49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.57.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=4 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49} do_test boundary3-2.57.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=4 ORDER BY x } } {49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.57.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=4 - ORDER BY t1.oid + ORDER BY t1.rowid } } {49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.57.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=4 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49} do_test boundary3-2.57.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 127 ORDER BY t2.a + WHERE t1.rowid >= 127 ORDER BY t2.a } } {3 4 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 34 35 36 39 40 42 43 45 46 48 49 50 51 56 57 61 62} do_test boundary3-2.57.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 127 ORDER BY t1.a DESC + WHERE t1.rowid >= 127 ORDER BY t1.a DESC } } {62 61 57 56 51 50 49 48 46 45 43 42 40 39 36 35 34 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 4 3} do_test boundary3-2.57.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=4 - ORDER BY t1.oid + ORDER BY t1.rowid } } {4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.57.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=4 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4} do_test boundary3-2.57.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=4 ORDER BY x } } {4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.57.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=4 - ORDER BY t1.oid + ORDER BY t1.rowid } } {4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.57.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=4 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4} do_test boundary3-2.57.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 127 ORDER BY t2.a + WHERE t1.rowid < 127 ORDER BY t2.a } } {1 2 5 11 21 29 31 32 33 37 38 41 44 47 52 53 54 55 58 59 60 63 64} do_test boundary3-2.57.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 127 ORDER BY t1.a DESC + WHERE t1.rowid < 127 ORDER BY t1.a DESC } } {64 63 60 59 58 55 54 53 52 47 44 41 38 37 33 32 31 29 21 11 5 2 1} do_test boundary3-2.57.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=4 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31} do_test boundary3-2.57.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=4 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.57.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=4 ORDER BY x } } {59 60 41 5 31 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.57.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=4 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31} do_test boundary3-2.57.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=4 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.57.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 127 ORDER BY t2.a + WHERE t1.rowid <= 127 ORDER BY t2.a } } {1 2 4 5 11 21 29 31 32 33 37 38 41 44 47 52 53 54 55 58 59 60 63 64} do_test boundary3-2.57.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 127 ORDER BY t1.a DESC + WHERE t1.rowid <= 127 ORDER BY t1.a DESC } } {64 63 60 59 58 55 54 53 52 47 44 41 38 37 33 32 31 29 21 11 5 4 2 1} do_test boundary3-2.57.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=4 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4} do_test boundary3-2.57.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=4 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.57.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=4 ORDER BY x } } {59 60 41 5 31 4 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.57.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=4 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4} do_test boundary3-2.57.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=4 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.58.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=36028797018963967 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=36028797018963967 AND t2.a=t1.a } } {27 007fffffffffffff} do_test boundary3-2.58.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='007fffffffffffff' } } {36028797018963967 27} do_test boundary3-2.58.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=27 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=27 } } {36028797018963967 007fffffffffffff} do_test boundary3-2.58.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 36028797018963967 ORDER BY t2.a + WHERE t1.rowid > 36028797018963967 ORDER BY t2.a } } {3 17 28 45} do_test boundary3-2.58.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 36028797018963967 ORDER BY t1.a DESC + WHERE t1.rowid > 36028797018963967 ORDER BY t1.a DESC } } {45 28 17 3} do_test boundary3-2.58.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=27 - ORDER BY t1.oid + ORDER BY t1.rowid } } {45 17 28 3} do_test boundary3-2.58.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=27 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45} do_test boundary3-2.58.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=27 ORDER BY x } } {45 17 28 3} do_test boundary3-2.58.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 36028797018963967 ORDER BY t2.a + WHERE t1.rowid >= 36028797018963967 ORDER BY t2.a } } {3 17 27 28 45} do_test boundary3-2.58.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 36028797018963967 ORDER BY t1.a DESC + WHERE t1.rowid >= 36028797018963967 ORDER BY t1.a DESC } } {45 28 27 17 3} do_test boundary3-2.58.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=27 - ORDER BY t1.oid + ORDER BY t1.rowid } } {27 45 17 28 3} do_test boundary3-2.58.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=27 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27} do_test boundary3-2.58.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=27 ORDER BY x } } {27 45 17 28 3} do_test boundary3-2.58.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 36028797018963967 ORDER BY t2.a + WHERE t1.rowid < 36028797018963967 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 10 11 12 13 14 15 16 18 19 20 21 22 23 24 25 26 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.58.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 36028797018963967 ORDER BY t1.a DESC + WHERE t1.rowid < 36028797018963967 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 26 25 24 23 22 21 20 19 18 16 15 14 13 12 11 10 9 8 7 6 5 4 2 1} do_test boundary3-2.58.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=27 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43} do_test boundary3-2.58.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=27 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.58.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=27 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.58.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 36028797018963967 ORDER BY t2.a + WHERE t1.rowid <= 36028797018963967 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 10 11 12 13 14 15 16 18 19 20 21 22 23 24 25 26 27 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.58.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 36028797018963967 ORDER BY t1.a DESC + WHERE t1.rowid <= 36028797018963967 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 27 26 25 24 23 22 21 20 19 18 16 15 14 13 12 11 10 9 8 7 6 5 4 2 1} do_test boundary3-2.58.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=27 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27} do_test boundary3-2.58.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=27 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.58.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=27 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.59.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=4398046511104 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=4398046511104 AND t2.a=t1.a } } {56 0000040000000000} do_test boundary3-2.59.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000040000000000' } } {4398046511104 56} do_test boundary3-2.59.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=56 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=56 } } {4398046511104 0000040000000000} do_test boundary3-2.59.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 4398046511104 ORDER BY t2.a + WHERE t1.rowid > 4398046511104 ORDER BY t2.a } } {3 10 13 17 25 26 27 28 34 43 45} do_test boundary3-2.59.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 4398046511104 ORDER BY t1.a DESC + WHERE t1.rowid > 4398046511104 ORDER BY t1.a DESC } } {45 43 34 28 27 26 25 17 13 10 3} do_test boundary3-2.59.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=56 - ORDER BY t1.oid + ORDER BY t1.rowid } } {25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.59.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=56 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25} do_test boundary3-2.59.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=56 ORDER BY x } } {25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.59.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=56 - ORDER BY t1.oid + ORDER BY t1.rowid } } {25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.59.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=56 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25} do_test boundary3-2.59.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 4398046511104 ORDER BY t2.a + WHERE t1.rowid >= 4398046511104 ORDER BY t2.a } } {3 10 13 17 25 26 27 28 34 43 45 56} do_test boundary3-2.59.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 4398046511104 ORDER BY t1.a DESC + WHERE t1.rowid >= 4398046511104 ORDER BY t1.a DESC } } {56 45 43 34 28 27 26 25 17 13 10 3} do_test boundary3-2.59.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=56 - ORDER BY t1.oid + ORDER BY t1.rowid } } {56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.59.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=56 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56} do_test boundary3-2.59.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=56 ORDER BY x } } {56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.59.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=56 - ORDER BY t1.oid + ORDER BY t1.rowid } } {56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.59.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=56 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56} do_test boundary3-2.59.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 4398046511104 ORDER BY t2.a + WHERE t1.rowid < 4398046511104 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 11 12 14 15 16 18 19 20 21 22 23 24 29 30 31 32 33 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 57 58 59 60 61 62 63 64} do_test boundary3-2.59.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 4398046511104 ORDER BY t1.a DESC + WHERE t1.rowid < 4398046511104 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 33 32 31 30 29 24 23 22 21 20 19 18 16 15 14 12 11 9 8 7 6 5 4 2 1} do_test boundary3-2.59.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=56 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7} do_test boundary3-2.59.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=56 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.59.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=56 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.59.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=56 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7} do_test boundary3-2.59.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=56 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.59.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 4398046511104 ORDER BY t2.a + WHERE t1.rowid <= 4398046511104 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 11 12 14 15 16 18 19 20 21 22 23 24 29 30 31 32 33 35 36 37 38 39 40 41 42 44 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.59.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 4398046511104 ORDER BY t1.a DESC + WHERE t1.rowid <= 4398046511104 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 44 42 41 40 39 38 37 36 35 33 32 31 30 29 24 23 22 21 20 19 18 16 15 14 12 11 9 8 7 6 5 4 2 1} do_test boundary3-2.59.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=56 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56} do_test boundary3-2.59.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=56 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.59.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=56 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.59.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=56 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56} do_test boundary3-2.59.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=56 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.60.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=1 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=1 AND t2.a=t1.a } } {60 0000000000000001} do_test boundary3-2.60.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000000000001' } } {1 60} do_test boundary3-2.60.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=60 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=60 } } {1 0000000000000001} do_test boundary3-2.60.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 1 ORDER BY t2.a + WHERE t1.rowid > 1 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 34 35 36 39 40 41 42 43 45 46 48 49 50 51 56 57 61 62} do_test boundary3-2.60.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 1 ORDER BY t1.a DESC + WHERE t1.rowid > 1 ORDER BY t1.a DESC } } {62 61 57 56 51 50 49 48 46 45 43 42 41 40 39 36 35 34 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.60.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=60 - ORDER BY t1.oid + ORDER BY t1.rowid } } {41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.60.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=60 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41} do_test boundary3-2.60.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=60 ORDER BY x } } {41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.60.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=60 - ORDER BY t1.oid + ORDER BY t1.rowid } } {41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.60.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=60 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41} do_test boundary3-2.60.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 1 ORDER BY t2.a + WHERE t1.rowid >= 1 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 34 35 36 39 40 41 42 43 45 46 48 49 50 51 56 57 60 61 62} do_test boundary3-2.60.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 1 ORDER BY t1.a DESC + WHERE t1.rowid >= 1 ORDER BY t1.a DESC } } {62 61 60 57 56 51 50 49 48 46 45 43 42 41 40 39 36 35 34 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.60.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=60 - ORDER BY t1.oid + ORDER BY t1.rowid } } {60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.60.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=60 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60} do_test boundary3-2.60.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=60 ORDER BY x } } {60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.60.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=60 - ORDER BY t1.oid + ORDER BY t1.rowid } } {60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.60.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=60 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60} do_test boundary3-2.60.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 1 ORDER BY t2.a + WHERE t1.rowid < 1 ORDER BY t2.a } } {1 2 11 21 29 32 33 37 38 44 47 52 53 54 55 58 59 63 64} do_test boundary3-2.60.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 1 ORDER BY t1.a DESC + WHERE t1.rowid < 1 ORDER BY t1.a DESC } } {64 63 59 58 55 54 53 52 47 44 38 37 33 32 29 21 11 2 1} do_test boundary3-2.60.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=60 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59} do_test boundary3-2.60.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=60 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.60.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=60 ORDER BY x } } {59 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.60.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=60 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59} do_test boundary3-2.60.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=60 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.60.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 1 ORDER BY t2.a + WHERE t1.rowid <= 1 ORDER BY t2.a } } {1 2 11 21 29 32 33 37 38 44 47 52 53 54 55 58 59 60 63 64} do_test boundary3-2.60.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 1 ORDER BY t1.a DESC + WHERE t1.rowid <= 1 ORDER BY t1.a DESC } } {64 63 60 59 58 55 54 53 52 47 44 38 37 33 32 29 21 11 2 1} do_test boundary3-2.60.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=60 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60} do_test boundary3-2.60.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=60 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.60.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=60 ORDER BY x } } {59 60 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.60.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=60 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60} do_test boundary3-2.60.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=60 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.61.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=36028797018963968 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=36028797018963968 AND t2.a=t1.a } } {45 0080000000000000} do_test boundary3-2.61.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0080000000000000' } } {36028797018963968 45} do_test boundary3-2.61.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=45 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=45 } } {36028797018963968 0080000000000000} do_test boundary3-2.61.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 36028797018963968 ORDER BY t2.a + WHERE t1.rowid > 36028797018963968 ORDER BY t2.a } } {3 17 28} do_test boundary3-2.61.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 36028797018963968 ORDER BY t1.a DESC + WHERE t1.rowid > 36028797018963968 ORDER BY t1.a DESC } } {28 17 3} do_test boundary3-2.61.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=45 - ORDER BY t1.oid + ORDER BY t1.rowid } } {17 28 3} do_test boundary3-2.61.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=45 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17} do_test boundary3-2.61.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=45 ORDER BY x } } {17 28 3} do_test boundary3-2.61.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 36028797018963968 ORDER BY t2.a + WHERE t1.rowid >= 36028797018963968 ORDER BY t2.a } } {3 17 28 45} do_test boundary3-2.61.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 36028797018963968 ORDER BY t1.a DESC + WHERE t1.rowid >= 36028797018963968 ORDER BY t1.a DESC } } {45 28 17 3} do_test boundary3-2.61.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=45 - ORDER BY t1.oid + ORDER BY t1.rowid } } {45 17 28 3} do_test boundary3-2.61.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=45 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45} do_test boundary3-2.61.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=45 ORDER BY x } } {45 17 28 3} do_test boundary3-2.61.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 36028797018963968 ORDER BY t2.a + WHERE t1.rowid < 36028797018963968 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 10 11 12 13 14 15 16 18 19 20 21 22 23 24 25 26 27 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.61.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 36028797018963968 ORDER BY t1.a DESC + WHERE t1.rowid < 36028797018963968 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 27 26 25 24 23 22 21 20 19 18 16 15 14 13 12 11 10 9 8 7 6 5 4 2 1} do_test boundary3-2.61.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=45 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27} do_test boundary3-2.61.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=45 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.61.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=45 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.61.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 36028797018963968 ORDER BY t2.a + WHERE t1.rowid <= 36028797018963968 ORDER BY t2.a } } {1 2 4 5 6 7 8 9 10 11 12 13 14 15 16 18 19 20 21 22 23 24 25 26 27 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.61.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 36028797018963968 ORDER BY t1.a DESC + WHERE t1.rowid <= 36028797018963968 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 27 26 25 24 23 22 21 20 19 18 16 15 14 13 12 11 10 9 8 7 6 5 4 2 1} do_test boundary3-2.61.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=45 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45} do_test boundary3-2.61.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=45 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.61.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=45 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.62.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=-2147483649 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=-2147483649 AND t2.a=t1.a } } {47 ffffffff7fffffff} do_test boundary3-2.62.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='ffffffff7fffffff' } } {-2147483649 47} do_test boundary3-2.62.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=47 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=47 } } {-2147483649 ffffffff7fffffff} do_test boundary3-2.62.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -2147483649 ORDER BY t2.a + WHERE t1.rowid > -2147483649 ORDER BY t2.a } } {1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 45 46 48 49 50 51 52 53 54 56 57 59 60 61 62} do_test boundary3-2.62.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -2147483649 ORDER BY t1.a DESC + WHERE t1.rowid > -2147483649 ORDER BY t1.a DESC } } {62 61 60 59 57 56 54 53 52 51 50 49 48 46 45 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 1} do_test boundary3-2.62.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=47 - ORDER BY t1.oid + ORDER BY t1.rowid } } {11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.62.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=47 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11} do_test boundary3-2.62.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=47 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.62.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=47 - ORDER BY t1.oid + ORDER BY t1.rowid } } {11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.62.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=47 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11} do_test boundary3-2.62.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -2147483649 ORDER BY t2.a + WHERE t1.rowid >= -2147483649 ORDER BY t2.a } } {1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 45 46 47 48 49 50 51 52 53 54 56 57 59 60 61 62} do_test boundary3-2.62.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -2147483649 ORDER BY t1.a DESC + WHERE t1.rowid >= -2147483649 ORDER BY t1.a DESC } } {62 61 60 59 57 56 54 53 52 51 50 49 48 47 46 45 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 1} do_test boundary3-2.62.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=47 - ORDER BY t1.oid + ORDER BY t1.rowid } } {47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.62.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=47 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47} do_test boundary3-2.62.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=47 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.62.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=47 - ORDER BY t1.oid + ORDER BY t1.rowid } } {47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.62.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=47 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47} do_test boundary3-2.62.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -2147483649 ORDER BY t2.a + WHERE t1.rowid < -2147483649 ORDER BY t2.a } } {2 21 44 55 58 63 64} do_test boundary3-2.62.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -2147483649 ORDER BY t1.a DESC + WHERE t1.rowid < -2147483649 ORDER BY t1.a DESC } } {64 63 58 55 44 21 2} do_test boundary3-2.62.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=47 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63} do_test boundary3-2.62.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=47 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {63 58 44 21 64 2 55} do_test boundary3-2.62.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=47 ORDER BY x } } {55 2 64 21 44 58 63} do_test boundary3-2.62.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=47 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63} do_test boundary3-2.62.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=47 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {63 58 44 21 64 2 55} do_test boundary3-2.62.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -2147483649 ORDER BY t2.a + WHERE t1.rowid <= -2147483649 ORDER BY t2.a } } {2 21 44 47 55 58 63 64} do_test boundary3-2.62.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -2147483649 ORDER BY t1.a DESC + WHERE t1.rowid <= -2147483649 ORDER BY t1.a DESC } } {64 63 58 55 47 44 21 2} do_test boundary3-2.62.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=47 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47} do_test boundary3-2.62.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=47 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {47 63 58 44 21 64 2 55} do_test boundary3-2.62.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=47 ORDER BY x } } {55 2 64 21 44 58 63 47} do_test boundary3-2.62.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=47 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47} do_test boundary3-2.62.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=47 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {47 63 58 44 21 64 2 55} do_test boundary3-2.63.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=-36028797018963969 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=-36028797018963969 AND t2.a=t1.a } } {2 ff7fffffffffffff} do_test boundary3-2.63.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='ff7fffffffffffff' } } {-36028797018963969 2} do_test boundary3-2.63.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=2 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=2 } } {-36028797018963969 ff7fffffffffffff} do_test boundary3-2.63.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -36028797018963969 ORDER BY t2.a + WHERE t1.rowid > -36028797018963969 ORDER BY t2.a } } {1 3 4 5 6 7 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 42 43 44 45 46 47 48 49 50 51 52 53 54 56 57 58 59 60 61 62 63 64} do_test boundary3-2.63.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -36028797018963969 ORDER BY t1.a DESC + WHERE t1.rowid > -36028797018963969 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 1} do_test boundary3-2.63.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=2 - ORDER BY t1.oid + ORDER BY t1.rowid } } {64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.63.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=2 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64} do_test boundary3-2.63.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=2 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.63.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -36028797018963969 ORDER BY t2.a + WHERE t1.rowid >= -36028797018963969 ORDER BY t2.a } } {1 2 3 4 5 6 7 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 42 43 44 45 46 47 48 49 50 51 52 53 54 56 57 58 59 60 61 62 63 64} do_test boundary3-2.63.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -36028797018963969 ORDER BY t1.a DESC + WHERE t1.rowid >= -36028797018963969 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1} do_test boundary3-2.63.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=2 - ORDER BY t1.oid + ORDER BY t1.rowid } } {2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.63.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=2 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2} do_test boundary3-2.63.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=2 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.63.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -36028797018963969 ORDER BY t2.a + WHERE t1.rowid < -36028797018963969 ORDER BY t2.a } } {55} do_test boundary3-2.63.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -36028797018963969 ORDER BY t1.a DESC + WHERE t1.rowid < -36028797018963969 ORDER BY t1.a DESC } } {55} do_test boundary3-2.63.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=2 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55} do_test boundary3-2.63.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=2 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {55} do_test boundary3-2.63.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=2 ORDER BY x } } {55} do_test boundary3-2.63.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -36028797018963969 ORDER BY t2.a + WHERE t1.rowid <= -36028797018963969 ORDER BY t2.a } } {2 55} do_test boundary3-2.63.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -36028797018963969 ORDER BY t1.a DESC + WHERE t1.rowid <= -36028797018963969 ORDER BY t1.a DESC } } {55 2} do_test boundary3-2.63.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=2 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2} do_test boundary3-2.63.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=2 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {2 55} do_test boundary3-2.63.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=2 ORDER BY x } } {55 2} do_test boundary3-2.64.1 { db eval { - SELECT t1.a,t1.x FROM t1, t2 WHERE t1.oid=3 AND t2.a=t1.a + SELECT t1.* FROM t1, t2 WHERE t1.rowid=3 AND t2.a=t1.a } } {5 0000000000000003} do_test boundary3-2.64.2 { db eval { SELECT t2.* FROM t1 JOIN t2 USING(a) WHERE x='0000000000000003' } } {3 5} do_test boundary3-2.64.3 { db eval { - SELECT t1.oid, x FROM t1 JOIN t2 ON t2.r=t1.oid WHERE t2.a=5 + SELECT t1.rowid, x FROM t1 JOIN t2 ON t2.r=t1.rowid WHERE t2.a=5 } } {3 0000000000000003} do_test boundary3-2.64.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 3 ORDER BY t2.a + WHERE t1.rowid > 3 ORDER BY t2.a } } {3 4 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 34 35 36 39 40 42 43 45 46 48 49 50 51 56 57 61 62} do_test boundary3-2.64.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 3 ORDER BY t1.a DESC + WHERE t1.rowid > 3 ORDER BY t1.a DESC } } {62 61 57 56 51 50 49 48 46 45 43 42 40 39 36 35 34 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 4 3} do_test boundary3-2.64.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=5 - ORDER BY t1.oid + ORDER BY t1.rowid } } {31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.64.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=5 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31} do_test boundary3-2.64.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=5 ORDER BY x } } {31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.64.gt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=5 - ORDER BY t1.oid + ORDER BY t1.rowid } } {31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.64.gt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > CAST(t2.r AS real) WHERE t2.a=5 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31} do_test boundary3-2.64.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 3 ORDER BY t2.a + WHERE t1.rowid >= 3 ORDER BY t2.a } } {3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 30 31 34 35 36 39 40 42 43 45 46 48 49 50 51 56 57 61 62} do_test boundary3-2.64.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 3 ORDER BY t1.a DESC + WHERE t1.rowid >= 3 ORDER BY t1.a DESC } } {62 61 57 56 51 50 49 48 46 45 43 42 40 39 36 35 34 31 30 28 27 26 25 24 23 22 20 19 18 17 16 15 14 13 12 10 9 8 7 6 5 4 3} do_test boundary3-2.64.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=5 - ORDER BY t1.oid + ORDER BY t1.rowid } } {5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.64.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=5 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5} do_test boundary3-2.64.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=5 ORDER BY x } } {5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.64.ge.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=5 - ORDER BY t1.oid + ORDER BY t1.rowid } } {5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.64.ge.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= CAST(t2.r AS real) WHERE t2.a=5 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5} do_test boundary3-2.64.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 3 ORDER BY t2.a + WHERE t1.rowid < 3 ORDER BY t2.a } } {1 2 11 21 29 32 33 37 38 41 44 47 52 53 54 55 58 59 60 63 64} do_test boundary3-2.64.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 3 ORDER BY t1.a DESC + WHERE t1.rowid < 3 ORDER BY t1.a DESC } } {64 63 60 59 58 55 54 53 52 47 44 41 38 37 33 32 29 21 11 2 1} do_test boundary3-2.64.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=5 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41} do_test boundary3-2.64.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=5 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.64.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=5 ORDER BY x } } {59 60 41 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.64.lt.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=5 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41} do_test boundary3-2.64.lt.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < CAST(t2.r AS real) WHERE t2.a=5 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.64.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 3 ORDER BY t2.a + WHERE t1.rowid <= 3 ORDER BY t2.a } } {1 2 5 11 21 29 32 33 37 38 41 44 47 52 53 54 55 58 59 60 63 64} do_test boundary3-2.64.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 3 ORDER BY t1.a DESC + WHERE t1.rowid <= 3 ORDER BY t1.a DESC } } {64 63 60 59 58 55 54 53 52 47 44 41 38 37 33 32 29 21 11 5 2 1} do_test boundary3-2.64.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=5 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5} do_test boundary3-2.64.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=5 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.64.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=5 ORDER BY x } } {59 60 41 5 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.64.le.10 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=5 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5} do_test boundary3-2.64.le.11 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= CAST(t2.r AS real) + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= CAST(t2.r AS real) WHERE t2.a=5 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.65.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > 9.22337303685477580800e+18 ORDER BY t2.a + WHERE t1.rowid > 9.22337303685477580800e+18 ORDER BY t2.a } } {} do_test boundary3-2.65.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > 9.22337303685477580800e+18 ORDER BY t1.a DESC + WHERE t1.rowid > 9.22337303685477580800e+18 ORDER BY t1.a DESC } } {} do_test boundary3-2.65.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=65 - ORDER BY t1.oid + ORDER BY t1.rowid } } {} do_test boundary3-2.65.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=65 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {} do_test boundary3-2.65.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=65 ORDER BY x } } {} do_test boundary3-2.65.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= 9.22337303685477580800e+18 ORDER BY t2.a + WHERE t1.rowid >= 9.22337303685477580800e+18 ORDER BY t2.a } } {} do_test boundary3-2.65.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= 9.22337303685477580800e+18 ORDER BY t1.a DESC + WHERE t1.rowid >= 9.22337303685477580800e+18 ORDER BY t1.a DESC } } {} do_test boundary3-2.65.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=65 - ORDER BY t1.oid + ORDER BY t1.rowid } } {} do_test boundary3-2.65.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=65 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {} do_test boundary3-2.65.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=65 ORDER BY x } } {} do_test boundary3-2.65.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < 9.22337303685477580800e+18 ORDER BY t2.a + WHERE t1.rowid < 9.22337303685477580800e+18 ORDER BY t2.a } } {1 2 3 4 5 6 7 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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.65.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < 9.22337303685477580800e+18 ORDER BY t1.a DESC + WHERE t1.rowid < 9.22337303685477580800e+18 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1} do_test boundary3-2.65.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=65 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.65.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=65 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.65.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=65 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.65.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= 9.22337303685477580800e+18 ORDER BY t2.a + WHERE t1.rowid <= 9.22337303685477580800e+18 ORDER BY t2.a } } {1 2 3 4 5 6 7 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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.65.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= 9.22337303685477580800e+18 ORDER BY t1.a DESC + WHERE t1.rowid <= 9.22337303685477580800e+18 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1} do_test boundary3-2.65.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=65 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.65.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=65 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.65.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=65 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.66.gt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid > -9.22337303685477580800e+18 ORDER BY t2.a + WHERE t1.rowid > -9.22337303685477580800e+18 ORDER BY t2.a } } {1 2 3 4 5 6 7 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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.66.gt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid > -9.22337303685477580800e+18 ORDER BY t1.a DESC + WHERE t1.rowid > -9.22337303685477580800e+18 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1} do_test boundary3-2.66.gt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=66 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.66.gt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=66 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.66.gt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid > t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid > t2.r WHERE t2.a=66 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.66.ge.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid >= -9.22337303685477580800e+18 ORDER BY t2.a + WHERE t1.rowid >= -9.22337303685477580800e+18 ORDER BY t2.a } } {1 2 3 4 5 6 7 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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} do_test boundary3-2.66.ge.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid >= -9.22337303685477580800e+18 ORDER BY t1.a DESC + WHERE t1.rowid >= -9.22337303685477580800e+18 ORDER BY t1.a DESC } } {64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1} do_test boundary3-2.66.ge.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=66 - ORDER BY t1.oid + ORDER BY t1.rowid } } {55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38 59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3} do_test boundary3-2.66.ge.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=66 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {3 28 17 45 27 43 13 26 10 34 25 56 7 19 57 35 46 22 39 36 14 51 20 40 12 6 9 24 18 42 15 62 48 50 23 16 8 61 30 49 4 31 5 41 60 59 38 33 52 53 54 32 29 37 1 11 47 63 58 44 21 64 2 55} do_test boundary3-2.66.ge.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid >= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid >= t2.r WHERE t2.a=66 ORDER BY x } } {59 60 41 5 31 4 49 30 61 8 16 23 50 48 62 15 42 18 24 9 6 12 40 20 51 14 36 39 22 46 35 57 19 7 56 25 34 10 26 13 43 27 45 17 28 3 55 2 64 21 44 58 63 47 11 1 37 29 32 54 53 52 33 38} do_test boundary3-2.66.lt.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid < -9.22337303685477580800e+18 ORDER BY t2.a + WHERE t1.rowid < -9.22337303685477580800e+18 ORDER BY t2.a } } {} do_test boundary3-2.66.lt.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid < -9.22337303685477580800e+18 ORDER BY t1.a DESC + WHERE t1.rowid < -9.22337303685477580800e+18 ORDER BY t1.a DESC } } {} do_test boundary3-2.66.lt.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=66 - ORDER BY t1.oid + ORDER BY t1.rowid } } {} do_test boundary3-2.66.lt.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=66 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {} do_test boundary3-2.66.lt.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid < t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid < t2.r WHERE t2.a=66 ORDER BY x } } {} do_test boundary3-2.66.le.1 { db eval { SELECT t2.a FROM t1 JOIN t2 USING(a) - WHERE t1.oid <= -9.22337303685477580800e+18 ORDER BY t2.a + WHERE t1.rowid <= -9.22337303685477580800e+18 ORDER BY t2.a } } {} do_test boundary3-2.66.le.2 { db eval { SELECT t2.a FROM t2 NATURAL JOIN t1 - WHERE t1.oid <= -9.22337303685477580800e+18 ORDER BY t1.a DESC + WHERE t1.rowid <= -9.22337303685477580800e+18 ORDER BY t1.a DESC } } {} do_test boundary3-2.66.le.3 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=66 - ORDER BY t1.oid + ORDER BY t1.rowid } } {} do_test boundary3-2.66.le.4 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=66 - ORDER BY t1.oid DESC + ORDER BY t1.rowid DESC } } {} do_test boundary3-2.66.le.5 { db eval { - SELECT t1.a FROM t1 JOIN t2 ON t1.oid <= t2.r + SELECT t1.a FROM t1 JOIN t2 ON t1.rowid <= t2.r WHERE t2.a=66 ORDER BY x } } {} finish_test Index: test/capi2.test ================================================================== --- test/capi2.test +++ test/capi2.test @@ -225,11 +225,11 @@ set VM [sqlite4_prepare $DB {INSERT INTO t1 VALUES(1,3,4)} -1 TAIL] list [sqlite4_step $VM] \ [sqlite4_column_count $VM] \ [get_row_values $VM] \ [get_column_names $VM] -} {SQLITE4_CONSTRAINT 0 {} {}} +} {SQLITE4_ERROR 0 {} {}} # Update for v3: Preparing a statement does not affect the change counter. # (Test result changes from 0 to 1). (Later:) change counter updates occur # when sqlite4_step returns, not at finalize time. do_test capi2-3.13b {db changes} {0} @@ -254,11 +254,11 @@ set VM [sqlite4_prepare $DB {INSERT INTO t2 VALUES(NULL,2)} -1 TAIL] list [sqlite4_step $VM] \ [sqlite4_column_count $VM] \ [get_row_values $VM] \ [get_column_names $VM] -} {SQLITE4_CONSTRAINT 0 {} {}} +} {SQLITE4_ERROR 0 {} {}} do_test capi2-3.19 { list [sqlite4_finalize $VM] [sqlite4_errmsg $DB] } {SQLITE4_CONSTRAINT {t2.a may not be NULL}} do_test capi2-3.20 { @@ -268,14 +268,14 @@ } } {} do_test capi2-3.21 { set VM [sqlite4_prepare $DB {INSERT INTO a1 VALUES(1, 1)} -1 TAIL] sqlite4_step $VM -} {SQLITE4_CONSTRAINT} +} {SQLITE4_ERROR} do_test capi2-3.22 { sqlite4_errcode $DB -} {SQLITE4_CONSTRAINT} +} {SQLITE4_ERROR} do_test capi2-3.23 { sqlite4_finalize $VM } {SQLITE4_CONSTRAINT} do_test capi2-3.24 { sqlite4_errcode $DB @@ -432,22 +432,22 @@ # list [sqlite4_step $VM1] \ # [sqlite4_column_count $VM1] \ # [get_row_values $VM1] \ # [get_column_names $VM1] # } {SQLITE4_BUSY 0 {} {}} -do_test capi2-6.5 { - catchsql {INSERT INTO t3 VALUES(10);} db2 -} {0 {}} do_test capi2-6.3 { execsql {COMMIT} db2 } {} do_test capi2-6.4 { list [sqlite4_step $VM1] \ [sqlite4_column_count $VM1] \ [get_row_values $VM1] \ [get_column_names $VM1] } {SQLITE4_ROW 1 1 {x counter}} +do_test capi2-6.5 { + catchsql {INSERT INTO t3 VALUES(10);} db2 +} {1 {database is locked}} do_test capi2-6.6 { list [sqlite4_step $VM1] \ [sqlite4_column_count $VM1] \ [get_row_values $VM1] \ [get_column_names $VM1] @@ -577,22 +577,22 @@ } {0} do_test capi2-7.3 { stepsql $DB { UPDATE t1 SET a=a+10; } -} {0} +} {0 1} do_test capi2-7.4 { stepsql $DB { INSERT INTO t1 SELECT a+1,b+1,c+1 FROM t1; } -} {0} +} {0 1} do_test capi2-7.4b {sqlite4_changes $DB} {1} do_test capi2-7.5 { stepsql $DB { UPDATE t1 SET a=a+10; } -} {0} +} {0 2} do_test capi2-7.5b {sqlite4_changes $DB} {2} do_test capi2-7.6 { stepsql $DB { SELECT * FROM t1; } @@ -599,11 +599,11 @@ } {0 21 2 3 22 3 4} do_test capi2-7.7 { stepsql $DB { INSERT INTO t1 SELECT a+2,b+2,c+2 FROM t1; } -} {0} +} {0 2} do_test capi2-7.8 { sqlite4_changes $DB } {2} do_test capi2-7.9 { stepsql $DB { @@ -613,11 +613,11 @@ do_test capi2-7.10 { stepsql $DB { UPDATE t1 SET a=a-20; SELECT * FROM t1; } -} {0 1 2 3 2 3 4 3 4 5 4 5 6} +} {0 4 1 2 3 2 3 4 3 4 5 4 5 6} # Update for version 3: A SELECT statement no longer resets the change # counter (Test result changes from 0 to 4). do_test capi2-7.11 { sqlite4_changes $DB Index: test/capi3.test ================================================================== --- test/capi3.test +++ test/capi3.test @@ -57,22 +57,22 @@ # set DB [sqlite4_connection_pointer db] do_test capi3-1.0 { - sqlite4_db_transaction_status $DB -} 0 + sqlite4_get_autocommit $DB +} 1 do_test capi3-1.1 { set STMT [sqlite4_prepare $DB {SELECT name FROM sqlite_master} -1 TAIL] sqlite4_finalize $STMT set TAIL } {} do_test capi3-1.2.1 { sqlite4_errcode $DB } {SQLITE4_OK} do_test capi3-1.2.2 { - sqlite4_errcode $DB + sqlite4_extended_errcode $DB } {SQLITE4_OK} do_test capi3-1.3 { sqlite4_errmsg $DB } {not an error} do_test capi3-1.4 { @@ -102,15 +102,61 @@ } {1} do_test capi3-1.8.1 { sqlite4_errcode $DB } {SQLITE4_ERROR} do_test capi3-1.8.2 { - sqlite4_errcode $DB + sqlite4_extended_errcode $DB } {SQLITE4_ERROR} do_test capi3-1.9 { sqlite4_errmsg $DB } {no such column: namex} + +ifcapable {utf16} { + do_test capi3-2.1 { + set sql16 [utf16 {SELECT name FROM sqlite_master}] + set STMT [sqlite4_prepare16 $DB $sql16 -1 ::TAIL] + sqlite4_finalize $STMT + utf8 $::TAIL + } {} + do_test capi3-2.2 { + set sql [utf16 {SELECT name FROM sqlite_master;SELECT 10}] + set STMT [sqlite4_prepare16 $DB $sql -1 TAIL] + sqlite4_finalize $STMT + utf8 $TAIL + } {SELECT 10} + do_test capi3-2.3 { + set sql [utf16 {SELECT namex FROM sqlite_master}] + catch { + set STMT [sqlite4_prepare16 $DB $sql -1] + } + } {1} + do_test capi3-2.4.1 { + sqlite4_errcode $DB + } {SQLITE4_ERROR} + do_test capi3-2.4.2 { + sqlite4_extended_errcode $DB + } {SQLITE4_ERROR} + do_test capi3-2.5 { + sqlite4_errmsg $DB + } {no such column: namex} + + ifcapable schema_pragmas { + do_test capi3-2.6 { + execsql {CREATE TABLE tablename(x)} + set sql16 [utf16 {PRAGMA table_info("TableName"); --excess text}] + set STMT [sqlite4_prepare16 $DB $sql16 -1] + sqlite4_step $STMT + } SQLITE4_ROW + do_test capi3-2.7 { + sqlite4_step $STMT + } SQLITE4_DONE + do_test capi3-2.8 { + sqlite4_finalize $STMT + } SQLITE4_OK + } + +} ;# endif utf16 # rename sqlite4_open sqlite4_open_old # proc sqlite4_open {fname options} {sqlite4_open_new $fname $options} do_test capi3-3.1 { @@ -123,11 +169,11 @@ } {SQLITE4_OK} do_test capi3-3.3 { catch { set db2 [sqlite4_open /bogus/path/test.db {}] } - sqlite4_errcode $db2 + sqlite4_extended_errcode $db2 } {SQLITE4_CANTOPEN} do_test capi3-3.4 { sqlite4_errmsg $db2 } {unable to open database file} do_test capi3-3.5 { @@ -137,10 +183,15 @@ sqlite4_close $db2 } {SQLITE4_MISUSE} do_test capi3-3.6.2-misuse { sqlite4_errmsg $db2 } {library routine called out of sequence} +ifcapable {utf16} { + do_test capi3-3.6.3-misuse { + utf8 [sqlite4_errmsg16 $db2] + } {library routine called out of sequence} +} do_test capi3-3.7 { set db2 [sqlite4_open] sqlite4_errcode $db2 } {SQLITE4_OK} @@ -148,10 +199,33 @@ sqlite4_close $db2 } {SQLITE4_OK} # rename sqlite4_open "" # rename sqlite4_open_old sqlite4_open + +ifcapable {utf16} { +do_test capi3-4.1 { + set db2 [sqlite4_open16 [utf16 test.db] {}] + sqlite4_errcode $db2 +} {SQLITE4_OK} +# FIX ME: Should test the db handle works. +do_test capi3-4.2 { + sqlite4_close $db2 +} {SQLITE4_OK} +do_test capi3-4.3 { + catch { + set db2 [sqlite4_open16 [utf16 /bogus/path/test.db] {}] + } + sqlite4_errcode $db2 +} {SQLITE4_CANTOPEN} +do_test capi3-4.4 { + utf8 [sqlite4_errmsg16 $db2] +} {unable to open database file} +do_test capi3-4.5 { + sqlite4_close $db2 +} {SQLITE4_OK} +} ;# utf16 # This proc is used to test the following API calls: # # sqlite4_column_count # sqlite4_column_name @@ -182,34 +256,72 @@ do_test $test.1 { set cnamelist [list] foreach i $idxlist {lappend cnamelist [sqlite4_column_name $STMT $i]} set cnamelist } $names + + # Column names in UTF-16 + ifcapable {utf16} { + do_test $test.2 { + set cnamelist [list] + foreach i $idxlist { + lappend cnamelist [utf8 [sqlite4_column_name16 $STMT $i]] + } + set cnamelist + } $names + } # Column names in UTF-8 do_test $test.3 { set cnamelist [list] foreach i $idxlist {lappend cnamelist [sqlite4_column_name $STMT $i]} set cnamelist } $names + + # Column names in UTF-16 + ifcapable {utf16} { + do_test $test.4 { + set cnamelist [list] + foreach i $idxlist { + lappend cnamelist [utf8 [sqlite4_column_name16 $STMT $i]] + } + set cnamelist + } $names + } # Column names in UTF-8 do_test $test.5 { set cnamelist [list] foreach i $idxlist {lappend cnamelist [sqlite4_column_decltype $STMT $i]} set cnamelist } $decltypes + + # Column declaration types in UTF-16 + ifcapable {utf16} { + do_test $test.6 { + set cnamelist [list] + foreach i $idxlist { + lappend cnamelist [utf8 [sqlite4_column_decltype16 $STMT $i]] + } + set cnamelist + } $decltypes + } + # Test some out of range conditions: ifcapable {utf16} { do_test $test.7 { list \ [sqlite4_column_name $STMT -1] \ + [sqlite4_column_name16 $STMT -1] \ [sqlite4_column_decltype $STMT -1] \ + [sqlite4_column_decltype16 $STMT -1] \ [sqlite4_column_name $STMT $numcols] \ + [sqlite4_column_name16 $STMT $numcols] \ [sqlite4_column_decltype $STMT $numcols] \ - } {{} {} {} {}} + [sqlite4_column_decltype16 $STMT $numcols] + } {{} {} {} {} {} {} {} {}} } } # This proc is used to test the following API calls: # @@ -345,13 +457,42 @@ do_test $test.2 { set ints [list] foreach i $idxlist {lappend ints [sqlite4_column_int64 $STMT $i]} set ints } $ints + +# bytes +set lens [list] +foreach i $::idxlist { + lappend lens [string length [lindex $strings $i]] +} +do_test $test.3 { + set bytes [list] + set lens [list] + foreach i $idxlist { + lappend bytes [sqlite4_column_bytes $STMT $i] + } + set bytes +} $lens + +# bytes16 +ifcapable {utf16} { + set lens [list] + foreach i $::idxlist { + lappend lens [expr 2 * [string length [lindex $strings $i]]] + } + do_test $test.4 { + set bytes [list] + set lens [list] + foreach i $idxlist { + lappend bytes [sqlite4_column_bytes16 $STMT $i] + } + set bytes + } $lens +} # Blob -if {$test == "capi3-5.7"} breakpoint do_test $test.5 { set utf8 [list] foreach i $idxlist {lappend utf8 [sqlite4_column_blob $STMT $i]} set utf8 } $strings @@ -535,10 +676,24 @@ # This procedure returns the value of the file-format in file 'test.db'. # proc get_file_format {{fname test.db}} { return [hexio_get_int [hexio_read $fname 44 4]] } + +if {![sqlite4 -has-codec]} { + # Test what happens when the library encounters a newer file format. + do_test capi3-7.1 { + set_file_format 5 + } {} + do_test capi3-7.2 { + catch { sqlite4 db test.db } + catchsql { + SELECT * FROM sqlite_master; + } + } {1 {unsupported file format}} + db close +} if {![sqlite4 -has-codec]} { # Now test that the library correctly handles bogus entries in the # sqlite_master table (schema corruption). do_test capi3-8.1 { @@ -675,12 +830,12 @@ INSERT INTO t1 VALUES(1, 'int'); INSERT INTO t1 VALUES(2, 'notatype'); } } {} do_test capi3-11.1.1 { - sqlite4_db_transaction_status $DB -} 1 + sqlite4_get_autocommit $DB +} 0 do_test capi3-11.2 { set STMT [sqlite4_prepare $DB "SELECT func(b, a) FROM t1" -1 TAIL] sqlite4_step $STMT } {SQLITE4_ROW} @@ -691,15 +846,18 @@ catchsql { COMMIT; } } {0 {}} do_test capi3-11.3.2 { - sqlite4_errcode $DB + sqlite4_extended_errcode $DB } {SQLITE4_OK} do_test capi3-11.3.3 { - sqlite4_db_transaction_status $DB -} 0 + sqlite4_get_autocommit $DB +} 1 +do_test capi3-11.3.4 { + db eval {PRAGMA lock_status} +} {main shared temp closed} do_test capi3-11.4 { sqlite4_step $STMT } {SQLITE4_ERROR} do_test capi3-11.5 { @@ -709,12 +867,12 @@ catchsql { SELECT * FROM t1; } } {0 {1 int 2 notatype}} do_test capi3-11.7 { - sqlite4_db_transaction_status $DB -} 0 + sqlite4_get_autocommit $DB +} 1 do_test capi3-11.8 { execsql { CREATE TABLE t2(a); INSERT INTO t2 VALUES(1); INSERT INTO t2 VALUES(2); @@ -721,27 +879,27 @@ BEGIN; INSERT INTO t2 VALUES(3); } } {} do_test capi3-11.8.1 { - sqlite4_db_transaction_status $DB -} 1 + sqlite4_get_autocommit $DB +} 0 do_test capi3-11.9 { set STMT [sqlite4_prepare $DB "SELECT a FROM t2" -1 TAIL] sqlite4_step $STMT } {SQLITE4_ROW} do_test capi3-11.9.1 { - sqlite4_db_transaction_status $DB -} 1 + sqlite4_get_autocommit $DB +} 0 do_test capi3-11.9.2 { catchsql { ROLLBACK; } } {1 {cannot rollback transaction - SQL statements in progress}} do_test capi3-11.9.3 { - sqlite4_db_transaction_status $DB -} 1 + sqlite4_get_autocommit $DB +} 0 do_test capi3-11.10 { sqlite4_step $STMT } {SQLITE4_ROW} do_test capi3-11.11 { sqlite4_step $STMT @@ -756,20 +914,20 @@ execsql { SELECT a FROM t2; } } {1 2 3} do_test capi3-11.14.1 { - sqlite4_db_transaction_status $DB -} 1 + sqlite4_get_autocommit $DB +} 0 do_test capi3-11.15 { catchsql { ROLLBACK; } } {0 {}} do_test capi3-11.15.1 { - sqlite4_db_transaction_status $DB -} 0 + sqlite4_get_autocommit $DB +} 1 do_test capi3-11.16 { execsql { SELECT a FROM t2; } } {1 2} @@ -1040,7 +1198,18 @@ # range. # do_test capi3-19.1 { sqlite4_prepare_tkt3134 db } {} + +# Tests of the interface when no VFS is registered. +# +if {![info exists tester_do_binarylog]} { + db close + vfs_unregister_all + do_test capi3-20.1 { + sqlite4_sleep 100 + } {0} + vfs_reregister_all +} finish_test Index: test/check.test ================================================================== --- test/check.test +++ test/check.test @@ -115,11 +115,11 @@ } {4 11.0} do_test check-2.1 { execsql { CREATE TABLE t2( - x INTEGER CHECK( typeof(coalesce(x,0))=='integer' ), + x INTEGER CHECK( typeof(coalesce(x,0))=="integer" ), y REAL CHECK( typeof(coalesce(y,0.1))=='real' ), z TEXT CHECK( typeof(coalesce(z,''))=='text' ) ); } } {} @@ -146,16 +146,15 @@ catchsql { INSERT INTO t2 VALUES(NULL, 5, NULL); } } {1 {constraint failed}} do_test check-2.6 { - # This does not fail with src4. As CHECK constraints are evaluated after - # affinities are applied. catchsql { INSERT INTO t2 VALUES(NULL, NULL, 3.14159); } -} {0 {}} +} {1 {constraint failed}} + ifcapable subquery { do_test check-3.1 { catchsql { CREATE TABLE t3( x, y, z, @@ -273,10 +272,17 @@ catchsql { PRAGMA ignore_check_constraints=OFF; UPDATE t4 SET x=0, y=2; } } {1 {constraint failed}} +ifcapable vacuum { + do_test check_4.10 { + catchsql { + VACUUM + } + } {0 {}} +} do_test check-5.1 { catchsql { CREATE TABLE t5(x, y, CHECK( x*y<:abc ) Index: test/coalesce.test ================================================================== --- test/coalesce.test +++ test/coalesce.test @@ -67,10 +67,11 @@ FROM t1 ORDER BY a; } } {1 2 3 99 5 6 7 8} do_test coalesce-1.8 { db eval { +pragma vdbe_listing=on; SELECT coalesce( CASE WHEN b=2 THEN 123 END, CASE WHEN b=3 THEN 234 END, CASE WHEN c=3 THEN 345 WHEN c=33 THEN 456 END, d Index: test/collate2.test ================================================================== --- test/collate2.test +++ test/collate2.test @@ -639,17 +639,17 @@ do_test collate2-4.3 { execsql { SELECT collate2t1.a FROM collate2t1, collate2t3 WHERE collate2t1.b = collate2t3.b||''; } -} {AA Aa aA aa} +} {aa aA Aa AA} do_test collate2-4.4 { execsql { SELECT collate2t1.a FROM collate2t1, collate2t3 WHERE collate2t3.b||'' = collate2t1.b; } -} {AA Aa aA aa} +} {aa aA Aa AA} do_test collate2-4.5 { execsql { DROP TABLE collate2t3; } Index: test/collate4.test ================================================================== --- test/collate4.test +++ test/collate4.test @@ -434,11 +434,11 @@ CREATE INDEX collate4i1 ON collate4t1(a, b, c COLLATE text); } count { SELECT * FROM collate4t2 NATURAL JOIN collate4t1; } -} {0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1 1 1 25} +} {0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1 1 1 33} do_test collate4-2.2.10 { execsql { DROP TABLE collate4t1; DROP TABLE collate4t2; DELETED test/covidx.test Index: test/covidx.test ================================================================== --- test/covidx.test +++ /dev/null @@ -1,71 +0,0 @@ -# 2013 July 23 -# -# 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. -# -#*********************************************************************** -# This file implements regression tests for SQLite library. The -# focus of this file is testing the COVERING clause of the CREATE -# INDEX statement. -# - -set testdir [file dirname $argv0] -source $testdir/tester.tcl -set ::testprefix covidx - -#------------------------------------------------------------------------- -# -do_execsql_test 1.0 { - CREATE TABLE t1(a, b, c); - CREATE TABLE t2("123abc", "odd column name"); - CREATE TABLE "frivolous table name"(x, y); -} - -foreach {tn sql res} { - 1 { t1(a) COVERING(a, b, c) } {0 {}} - 2 { t1(a) COVERING ALL } {0 {}} - 3 { t2("123abc") COVERING ("odd column name") } {0 {}} - 4 { "frivolous table name"(x) COVERING (y) } {0 {}} - - 5 { t1(c) COVERING (d) } {1 {table t1 has no column named d}} - 6 { t1(c) COVERING () } {1 {near ")": syntax error}} -} { - do_catchsql_test 1.$tn "CREATE INDEX i1 ON $sql" $res - execsql { - DROP INDEX IF EXISTS i1; - } -} - -#------------------------------------------------------------------------- -# -do_execsql_test 2.1 { - CREATE TABLE x1(x); - CREATE INDEX xi1 ON x1(x) COVERING (x); - CREATE INDEX xi2 ON x1(x) COVERING ALL ; - - SELECT sql FROM sqlite_master where type = 'index'; -} { - {CREATE INDEX xi1 ON x1(x) COVERING (x)} - {CREATE INDEX xi2 ON x1(x) COVERING ALL} -} - -#------------------------------------------------------------------------- -# -reset_db -do_execsql_test 3.1 { - CREATE TABLE t1(a PRIMARY KEY, b, c); - CREATE INDEX i1 ON t1(b) COVERING(c, b); -} {} -do_execsql_test 3.2 { - INSERT INTO t1 VALUES(1, 'x', 'y'); -} {} -do_execsql_test 3.3 { - SELECT c FROM t1 ORDER BY b; -} {y} - -finish_test - Index: test/createtab.test ================================================================== --- test/createtab.test +++ test/createtab.test @@ -49,13 +49,13 @@ set isUtf16 0 ifcapable utf16 { set isUtf16 [expr {[execsql {PRAGMA encoding}] != "UTF-8"}] } - #do_test createtab-$av.2 { - # file size test.db - #} [expr {1024*(4+($av!=0)+(${isUtf16}*2))}] + do_test createtab-$av.2 { + file size test.db + } [expr {1024*(4+($av!=0)+(${isUtf16}*2))}] # Start reading the table # do_test createtab-$av.3 { set STMT [sqlite4_prepare db {SELECT x FROM t1} -1 TAIL] Index: test/descidx1.test ================================================================== --- test/descidx1.test +++ test/descidx1.test @@ -47,16 +47,18 @@ do_test descidx1-1.1 { execsql { CREATE TABLE t1(a,b); CREATE INDEX i1 ON t1(b ASC); } -} {} + get_file_format +} {4} do_test descidx1-1.2 { execsql { CREATE INDEX i2 ON t1(a DESC); } -} {} + get_file_format +} {4} # Put some information in the table and verify that the descending # index actually works. # do_test descidx1-2.1 { @@ -286,7 +288,77 @@ do_test descidx1-5.9 { cksort { SELECT a||b||c FROM t3 WHERE d=0 ORDER BY a DESC, b DESC, c ASC } } {110 111 100 101 010 011 000 001 sort} + +# Test the legacy_file_format pragma here because we have access to +# the get_file_format command. +# +ifcapable legacyformat { + do_test descidx1-6.1 { + db close + forcedelete test.db test.db-journal + sqlite4 db test.db + execsql {PRAGMA legacy_file_format} + } {1} +} else { + do_test descidx1-6.1 { + db close + forcedelete test.db test.db-journal + sqlite4 db test.db + execsql {PRAGMA legacy_file_format} + } {0} +} +do_test descidx1-6.2 { + execsql {PRAGMA legacy_file_format=YES} + execsql {PRAGMA legacy_file_format} +} {1} +do_test descidx1-6.3 { + execsql { + CREATE TABLE t1(a,b,c); + } + get_file_format +} {1} +ifcapable vacuum { + # Verify that the file format is preserved across a vacuum. + do_test descidx1-6.3.1 { + execsql {VACUUM} + get_file_format + } {1} +} +do_test descidx1-6.4 { + db close + forcedelete test.db test.db-journal + sqlite4 db test.db + execsql {PRAGMA legacy_file_format=NO} + execsql {PRAGMA legacy_file_format} +} {0} +do_test descidx1-6.5 { + execsql { + CREATE TABLE t1(a,b,c); + CREATE INDEX i1 ON t1(a ASC, b DESC, c ASC); + INSERT INTO t1 VALUES(1,2,3); + INSERT INTO t1 VALUES(1,1,0); + INSERT INTO t1 VALUES(1,2,1); + INSERT INTO t1 VALUES(1,3,4); + } + get_file_format +} {4} +ifcapable vacuum { + # Verify that the file format is preserved across a vacuum. + do_test descidx1-6.6 { + execsql {VACUUM} + get_file_format + } {4} + do_test descidx1-6.7 { + execsql { + PRAGMA legacy_file_format=ON; + VACUUM; + } + get_file_format + } {4} +} + + finish_test Index: test/descidx2.test ================================================================== --- test/descidx2.test +++ test/descidx2.test @@ -9,28 +9,69 @@ # #************************************************************************* # This file implements regression tests for SQLite library. The # focus of this script is descending indices. # +# $Id: descidx2.test,v 1.5 2008/03/19 00:21:31 drh Exp $ +# set testdir [file dirname $argv0] source $testdir/tester.tcl + +# Do not use a codec for tests in this file, as the database file is +# manipulated directly using tcl scripts (using the [hexio_write] command). +# +do_not_use_codec + + +db eval {PRAGMA legacy_file_format=OFF} + +# This procedure sets the value of the file-format in file 'test.db' +# to $newval. Also, the schema cookie is incremented. +# +proc set_file_format {newval} { + hexio_write test.db 44 [hexio_render_int32 $newval] + set schemacookie [hexio_get_int [hexio_read test.db 40 4]] + incr schemacookie + hexio_write test.db 40 [hexio_render_int32 $schemacookie] + return {} +} + +# This procedure returns the value of the file-format in file 'test.db'. +# +proc get_file_format {{fname test.db}} { + return [hexio_get_int [hexio_read $fname 44 4]] +} # Verify that the file format starts as 4 # do_test descidx2-1.1 { execsql { CREATE TABLE t1(a,b); CREATE INDEX i1 ON t1(b ASC); } -} {} + get_file_format +} {4} do_test descidx2-1.2 { execsql { CREATE INDEX i2 ON t1(a DESC); } -} {} + get_file_format +} {4} + +# Before adding any information to the database, set the file format +# back to three. Then close and reopen the database. With the file +# format set to three, SQLite should ignore the DESC argument on the +# index. +# +do_test descidx2-2.0 { + set_file_format 3 + db close + sqlite4 db test.db + get_file_format +} {3} # Put some information in the table and verify that the DESC # on the index is ignored. # do_test descidx2-2.1 { @@ -37,36 +78,36 @@ execsql { INSERT INTO t1 VALUES(1,1); INSERT INTO t1 VALUES(2,2); INSERT INTO t1 SELECT a+2, a+2 FROM t1; INSERT INTO t1 SELECT a+4, a+4 FROM t1; - SELECT b FROM t1 WHERE a>3 AND a<7 ORDER BY b ASC; + SELECT b FROM t1 WHERE a>3 AND a<7; } } {4 5 6} do_test descidx2-2.2 { execsql { - SELECT a FROM t1 WHERE b>3 AND b<7 ORDER BY a ASC; + SELECT a FROM t1 WHERE b>3 AND b<7; } } {4 5 6} do_test descidx2-2.3 { execsql { - SELECT b FROM t1 WHERE a>=3 AND a<7 ORDER BY b ASC; + SELECT b FROM t1 WHERE a>=3 AND a<7; } } {3 4 5 6} do_test descidx2-2.4 { execsql { - SELECT b FROM t1 WHERE a>3 AND a<=7 ORDER BY b ASC; + SELECT b FROM t1 WHERE a>3 AND a<=7; } } {4 5 6 7} do_test descidx2-2.5 { execsql { - SELECT b FROM t1 WHERE a>=3 AND a<=7 ORDER BY b ASC; + SELECT b FROM t1 WHERE a>=3 AND a<=7; } } {3 4 5 6 7} do_test descidx2-2.6 { execsql { - SELECT a FROM t1 WHERE b>=3 AND b<=7 ORDER BY a ASC; + SELECT a FROM t1 WHERE b>=3 AND b<=7; } } {3 4 5 6 7} # This procedure executes the SQL. Then it checks to see if the OP_Sort # opcode was executed. If an OP_Sort did occur, then "sort" is appended Index: test/descidx3.test ================================================================== --- test/descidx3.test +++ test/descidx3.test @@ -24,18 +24,39 @@ ifcapable !bloblit { finish_test return } +db eval {PRAGMA legacy_file_format=OFF} + +# This procedure sets the value of the file-format in file 'test.db' +# to $newval. Also, the schema cookie is incremented. +# +proc set_file_format {newval} { + hexio_write test.db 44 [hexio_render_int32 $newval] + set schemacookie [hexio_get_int [hexio_read test.db 40 4]] + incr schemacookie + hexio_write test.db 40 [hexio_render_int32 $schemacookie] + return {} +} + +# This procedure returns the value of the file-format in file 'test.db'. +# +proc get_file_format {{fname test.db}} { + return [hexio_get_int [hexio_read $fname 44 4]] +} +# Verify that the file format starts as 4. +# do_test descidx3-1.1 { execsql { CREATE TABLE t1(i INTEGER PRIMARY KEY,a,b,c,d); CREATE INDEX t1i1 ON t1(a DESC, b ASC, c DESC); CREATE INDEX t1i2 ON t1(b DESC, c ASC, d DESC); } -} {} + get_file_format +} {4} # Put some information in the table and verify that the descending # index actually works. # do_test descidx3-2.1 { @@ -109,15 +130,15 @@ ifcapable subquery { # If the subquery capability is not compiled in to the binary, then # the IN(...) operator is not available. Hence these tests cannot be # run. do_test descidx3-4.1 { - lsort [execsql { + execsql { UPDATE t1 SET a=2 WHERE i<6; SELECT i FROM t1 WHERE a IN (1,2) AND b>0 AND b<'zzz'; - }] - } {2 3 4 6 8} + } + } {8 6 2 4 3} do_test descidx3-4.2 { execsql { UPDATE t1 SET a=1; SELECT i FROM t1 WHERE a IN (1,2) AND b>0 AND b<'zzz'; } Index: test/distinct.test ================================================================== --- test/distinct.test +++ test/distinct.test @@ -13,15 +13,10 @@ # set testdir [file dirname $argv0] source $testdir/tester.tcl -ifcapable !compound { - finish_test - return -} - set testprefix distinct proc is_distinct_noop {sql} { set sql1 $sql @@ -75,48 +70,36 @@ CREATE UNIQUE INDEX i1 ON t1(b, c); CREATE UNIQUE INDEX i2 ON t1(d COLLATE nocase); CREATE TABLE t2(x INTEGER PRIMARY KEY, y); - CREATE TABLE t3(c1 PRIMARY KEY NOT NULL, c2 NOT NULL); + CREATE TABLE t3(c1 PRIMARY KEY, c2); CREATE INDEX i3 ON t3(c2); - - CREATE TABLE t4(a, b NOT NULL, c NOT NULL, d NOT NULL); - CREATE UNIQUE INDEX t4i1 ON t4(b, c); - CREATE UNIQUE INDEX t4i2 ON t4(d COLLATE nocase); } foreach {tn noop sql} { - 1.1 0 "SELECT DISTINCT b, c FROM t1" - 1.2 1 "SELECT DISTINCT b, c FROM t4" - 2.1 0 "SELECT DISTINCT c FROM t1 WHERE b = ?" - 2.2 1 "SELECT DISTINCT c FROM t4 WHERE b = ?" + 1 1 "SELECT DISTINCT b, c FROM t1" + 2 1 "SELECT DISTINCT c FROM t1 WHERE b = ?" 3 1 "SELECT DISTINCT rowid FROM t1" 4 1 "SELECT DISTINCT rowid, a FROM t1" 5 1 "SELECT DISTINCT x FROM t2" 6 1 "SELECT DISTINCT * FROM t2" 7 1 "SELECT DISTINCT * FROM (SELECT * FROM t2)" - 8.1 0 "SELECT DISTINCT * FROM t1" - 8.2 1 "SELECT DISTINCT * FROM t4" + 8 1 "SELECT DISTINCT * FROM t1" 8 0 "SELECT DISTINCT a, b FROM t1" 9 0 "SELECT DISTINCT c FROM t1 WHERE b IN (1,2)" 10 0 "SELECT DISTINCT c FROM t1" 11 0 "SELECT DISTINCT b FROM t1" - 12.1 0 "SELECT DISTINCT a, d FROM t1" - 12.2 0 "SELECT DISTINCT a, d FROM t4" - 13.1 0 "SELECT DISTINCT a, b, c COLLATE nocase FROM t1" - 13.2 0 "SELECT DISTINCT a, b, c COLLATE nocase FROM t4" - 14.1 0 "SELECT DISTINCT a, d COLLATE nocase FROM t1" - 14.2 1 "SELECT DISTINCT a, d COLLATE nocase FROM t4" - - 15 0 "SELECT DISTINCT a, d COLLATE binary FROM t1" - 16.1 0 "SELECT DISTINCT a, b, c COLLATE binary FROM t1" - 16.2 1 "SELECT DISTINCT a, b, c COLLATE binary FROM t4" + 12 0 "SELECT DISTINCT a, d FROM t1" + 13 0 "SELECT DISTINCT a, b, c COLLATE nocase FROM t1" + 14 1 "SELECT DISTINCT a, d COLLATE nocase FROM t1" + 15 0 "SELECT DISTINCT a, d COLLATE binary FROM t1" + 16 1 "SELECT DISTINCT a, b, c COLLATE binary FROM t1" 16 0 "SELECT DISTINCT t1.rowid FROM t1, t2" 17 0 { /* Technically, it would be possible to detect that DISTINCT ** is a no-op in cases like the following. But SQLite does not ** do so. */ @@ -129,12 +112,11 @@ 22 0 "SELECT DISTINCT * FROM (SELECT 1, 2, 3 UNION SELECT 4, 5, 6)" 24 0 "SELECT DISTINCT rowid/2 FROM t1" 25 1 "SELECT DISTINCT rowid/2, rowid FROM t1" - 26.1 0 "SELECT DISTINCT rowid/2, b FROM t1 WHERE c = ?" - 26.2 1 "SELECT DISTINCT rowid/2, b FROM t4 WHERE c = ?" + 26 1 "SELECT DISTINCT rowid/2, b FROM t1 WHERE c = ?" } { if {$noop} { do_distinct_noop_test 1.$tn $sql } else { do_distinct_not_noop_test 1.$tn $sql @@ -162,38 +144,22 @@ 1 "a, b FROM t1" {} {A B a b} 2 "b, a FROM t1" {} {B A b a} 3 "a, b, c FROM t1" {hash} {a b c A B C} 4 "a, b, c FROM t1 ORDER BY a, b, c" {btree} {A B C a b c} 5 "b FROM t1 WHERE a = 'a'" {} {b} - 6 "b FROM t1 ORDER BY +b COLLATE binary" {btree hash} {B b} + 6 "b FROM t1" {hash} {b B} 7 "a FROM t1" {} {A a} 8 "b COLLATE nocase FROM t1" {} {b} 9 "b COLLATE nocase FROM t1 ORDER BY b COLLATE nocase" {} {B} } { do_execsql_test 2.$tn.1 "SELECT DISTINCT $sql" $res # do_temptables_test 2.$tn.2 "SELECT DISTINCT $sql" $temptables } do_execsql_test 2.A { - SELECT (SELECT DISTINCT o.a FROM t1 AS i) FROM t1 AS o ORDER BY rowid; + SELECT (SELECT DISTINCT o.a FROM t1 AS i) FROM t1 AS o; } {a A a A} -do_test 3.0 { - db eval { - CREATE TABLE t3(a INTEGER, b INTEGER, c, UNIQUE(a,b)); - INSERT INTO t3 VALUES - (null, null, 1), - (null, null, 2), - (null, 3, 4), - (null, 3, 5), - (6, null, 7), - (6, null, 8); - SELECT DISTINCT a, b FROM t3 ORDER BY +a, +b; - } -} {{} {} {} 3 6 {}} -do_test 3.1 { - regexp {OpenEphemeral} [db eval { - EXPLAIN SELECT DISTINCT a, b FROM t3 ORDER BY +a, +b; - }] -} {0} + + finish_test Index: test/e_createtable.test ================================================================== --- test/e_createtable.test +++ test/e_createtable.test @@ -363,11 +363,11 @@ } { 1 "CREATE TABLE sqlite_abc(a, b, c)" sqlite_abc 2 "CREATE TABLE temp.sqlite_helloworld(x)" sqlite_helloworld 3 {CREATE TABLE auxa."sqlite__"(x, y)} sqlite__ 4 {CREATE TABLE auxb."sqlite_"(z)} sqlite_ - 5 {CREATE TABLE "SQLITE_TBL"(z)} SQLITE_TBL + 5 {CREATE TABLE "SQLITE4_TBL"(z)} SQLITE4_TBL } do_createtable_tests 1.1.2 { 1 "CREATE TABLE sqlit_abc(a, b, c)" {} 2 "CREATE TABLE temp.sqlitehelloworld(x)" {} 3 {CREATE TABLE auxa."sqlite"(x, y)} {} @@ -614,11 +614,11 @@ # The argument must be a table name. Return a list of column declared # types, from left to right, for the table. # proc sci {select cmd} { set res [list] - set STMT [sqlite4_prepare db $select -1 dummy] + set STMT [sqlite4_prepare_v2 db $select -1 dummy] for {set i 0} {$i < [sqlite4_column_count $STMT]} {incr i} { lappend res [$cmd $STMT $i] } sqlite4_finalize $STMT set res @@ -919,20 +919,20 @@ SELECT quote(a), quote(b), quote(c), quote(d), quote(e), quote(f), quote(g), quote(h), quote(i), quote(j), quote(k) FROM t4 ORDER BY rowid DESC LIMIT 1; } { 1 "INSERT INTO t4 DEFAULT VALUES" { - NULL {'string constant'} x'424c4f42' 1 -1 3.14 -3.14 + NULL {'string constant'} X'424C4F42' 1 -1 3.14 -3.14 'acd' '01:46:40' '2001-09-09' {'2001-09-09 01:46:40'} } 2 "INSERT INTO t4(a, b, c) VALUES(1, 2, 3)" { 1 2 3 1 -1 3.14 -3.14 'acd' '01:46:40' '2001-09-09' {'2001-09-09 01:46:40'} } 3 "INSERT INTO t4(k, j, i) VALUES(1, 2, 3)" { - NULL {'string constant'} x'424c4f42' 1 -1 3.14 -3.14 'acd' 3 2 1 + NULL {'string constant'} X'424C4F42' 1 -1 3.14 -3.14 'acd' 3 2 1 } 4 "INSERT INTO t4(a,b,c,d,e,f,g,h,i,j,k) VALUES(1,2,3,4,5,6,7,8,9,10,11)" { 1 2 3 4 5 6 7 8 9 10 11 } @@ -952,11 +952,11 @@ ); } {} do_execsql_test e_createtable-3.6.2 { INSERT INTO t5 DEFAULT VALUES; SELECT quote(a), quote(b), quote(c), quote(d), quote(e) FROM t5; -} {NULL {'text value'} x'424c4f42' -45678.6 394507} +} {NULL {'text value'} X'424C4F42' -45678.6 394507} # EVIDENCE-OF: R-60616-50251 If the default value of a column is an # expression in parentheses, then the expression is evaluated once for # each row inserted and the results used in the new row. # @@ -1087,11 +1087,11 @@ sqlite4_limit db SQLITE4_LIMIT_COLUMN [expr $::SQLITE4_MAX_COLUMN+2] do_catchsql_test e_createtable-3.11.3 [subst { CREATE TABLE t11([columns [expr $::SQLITE4_MAX_COLUMN+1]]); }] {1 {too many columns on t11}} -sqlite4_limit db SQLITE4_LIMIT_LENGTH 90013 +sqlite4_limit db SQLITE4_LIMIT_LENGTH 90010 do_execsql_test e_createtable-3.11.4 { CREATE TABLE t12(a, b, c); INSERT INTO t12 VALUES(randomblob(30000),randomblob(30000),randomblob(30000)); } {} do_catchsql_test e_createtable-3.11.5 { @@ -1183,22 +1183,22 @@ INSERT INTO t2 VALUES(45.5, 'one'); INSERT INTO t2 VALUES('brambles', 'two'); INSERT INTO t2 VALUES(X'ABCDEF', 'three'); } {} -do_createtable_tests 4.3.1 -error { PRIMARY KEY must be unique%s } { - 1 "INSERT INTO t1 VALUES(0, 0)" {""} - 2 "INSERT INTO t1 VALUES(45.5, 'abc')" {""} - 3 "INSERT INTO t1 VALUES(0.0, 'abc')" {""} - 4 "INSERT INTO t1 VALUES('brambles', 'abc')" {""} - 5 "INSERT INTO t1 VALUES(X'ABCDEF', 'abc')" {""} - - 6 "INSERT INTO t2 VALUES(0, 'zero')" {""} - 7 "INSERT INTO t2 VALUES(45.5, 'one')" {""} - 8 "INSERT INTO t2 VALUES(0.0, 'zero')" {""} - 9 "INSERT INTO t2 VALUES('brambles', 'two')" {""} - 10 "INSERT INTO t2 VALUES(X'ABCDEF', 'three')" {""} +do_createtable_tests 4.3.1 -error { %s not unique } { + 1 "INSERT INTO t1 VALUES(0, 0)" {"column x is"} + 2 "INSERT INTO t1 VALUES(45.5, 'abc')" {"column x is"} + 3 "INSERT INTO t1 VALUES(0.0, 'abc')" {"column x is"} + 4 "INSERT INTO t1 VALUES('brambles', 'abc')" {"column x is"} + 5 "INSERT INTO t1 VALUES(X'ABCDEF', 'abc')" {"column x is"} + + 6 "INSERT INTO t2 VALUES(0, 'zero')" {"columns x, y are"} + 7 "INSERT INTO t2 VALUES(45.5, 'one')" {"columns x, y are"} + 8 "INSERT INTO t2 VALUES(0.0, 'zero')" {"columns x, y are"} + 9 "INSERT INTO t2 VALUES('brambles', 'two')" {"columns x, y are"} + 10 "INSERT INTO t2 VALUES(X'ABCDEF', 'three')" {"columns x, y are"} } do_createtable_tests 4.3.2 { 1 "INSERT INTO t1 VALUES(-1, 0)" {} 2 "INSERT INTO t1 VALUES(45.2, 'abc')" {} 3 "INSERT INTO t1 VALUES(0.01, 'abc')" {} @@ -1209,52 +1209,64 @@ 7 "INSERT INTO t2 VALUES(45.5, 'abc')" {} 8 "INSERT INTO t2 VALUES(0.0, 'abc')" {} 9 "INSERT INTO t2 VALUES('brambles', 'abc')" {} 10 "INSERT INTO t2 VALUES(X'ABCDEF', 'abc')" {} } -do_createtable_tests 4.3.3 -error { PRIMARY KEY must be unique%s } { - 1 "UPDATE t1 SET x=0 WHERE y='two'" {""} - 2 "UPDATE t1 SET x='brambles' WHERE y='three'" {""} - 3 "UPDATE t1 SET x=45.5 WHERE y='zero'" {""} - 4 "UPDATE t1 SET x=X'ABCDEF' WHERE y='one'" {""} - 5 "UPDATE t1 SET x=0.0 WHERE y='three'" {""} - - 6 "UPDATE t2 SET x=0, y='zero' WHERE y='two'" {""} - 7 "UPDATE t2 SET x='brambles', y='two' WHERE y='three'" {""} - 8 "UPDATE t2 SET x=45.5, y='one' WHERE y='zero'" {""} - 9 "UPDATE t2 SET x=X'ABCDEF', y='three' WHERE y='one'" {""} - 10 "UPDATE t2 SET x=0.0, y='zero' WHERE y='three'" {""} -} - - -# src4 does not allow NULL values in primary key columns. -# -do_createtable_tests 4.4 -error { %s may not be NULL } { - 1 "INSERT INTO t1 VALUES(NULL, 0)" {t1.x} - 2 "INSERT INTO t1 VALUES(NULL, 0)" {t1.x} - 3 "INSERT INTO t1 VALUES(NULL, 0)" {t1.x} - - 4 "INSERT INTO t2 VALUES(NULL, 'zero')" {t2.x} - 5 "INSERT INTO t2 VALUES(NULL, 'one')" {t2.x} - 6 "INSERT INTO t2 VALUES(NULL, 'two')" {t2.x} - 7 "INSERT INTO t2 VALUES(NULL, 'three')" {t2.x} - - 8 "INSERT INTO t2 VALUES(0, NULL)" {t2.y} - 9 "INSERT INTO t2 VALUES(45.5, NULL)" {t2.y} - 10 "INSERT INTO t2 VALUES(0.0, NULL)" {t2.y} - 11 "INSERT INTO t2 VALUES('brambles', NULL)" {t2.y} - 12 "INSERT INTO t2 VALUES(X'ABCDEF', NULL)" {t2.y} - - 13 "INSERT INTO t2 VALUES(NULL, NULL)" {t2.x} - 14 "INSERT INTO t2 VALUES(NULL, NULL)" {t2.x} -} - +do_createtable_tests 4.3.3 -error { %s not unique } { + 1 "UPDATE t1 SET x=0 WHERE y='two'" {"column x is"} + 2 "UPDATE t1 SET x='brambles' WHERE y='three'" {"column x is"} + 3 "UPDATE t1 SET x=45.5 WHERE y='zero'" {"column x is"} + 4 "UPDATE t1 SET x=X'ABCDEF' WHERE y='one'" {"column x is"} + 5 "UPDATE t1 SET x=0.0 WHERE y='three'" {"column x is"} + + 6 "UPDATE t2 SET x=0, y='zero' WHERE y='two'" {"columns x, y are"} + 7 "UPDATE t2 SET x='brambles', y='two' WHERE y='three'" + {"columns x, y are"} + 8 "UPDATE t2 SET x=45.5, y='one' WHERE y='zero'" {"columns x, y are"} + 9 "UPDATE t2 SET x=X'ABCDEF', y='three' WHERE y='one'" + {"columns x, y are"} + 10 "UPDATE t2 SET x=0.0, y='zero' WHERE y='three'" + {"columns x, y are"} +} + + +# EVIDENCE-OF: R-52572-02078 For the purposes of determining the +# uniqueness of primary key values, NULL values are considered distinct +# from all other values, including other NULLs. +# +do_createtable_tests 4.4 { + 1 "INSERT INTO t1 VALUES(NULL, 0)" {} + 2 "INSERT INTO t1 VALUES(NULL, 0)" {} + 3 "INSERT INTO t1 VALUES(NULL, 0)" {} + + 4 "INSERT INTO t2 VALUES(NULL, 'zero')" {} + 5 "INSERT INTO t2 VALUES(NULL, 'one')" {} + 6 "INSERT INTO t2 VALUES(NULL, 'two')" {} + 7 "INSERT INTO t2 VALUES(NULL, 'three')" {} + + 8 "INSERT INTO t2 VALUES(0, NULL)" {} + 9 "INSERT INTO t2 VALUES(45.5, NULL)" {} + 10 "INSERT INTO t2 VALUES(0.0, NULL)" {} + 11 "INSERT INTO t2 VALUES('brambles', NULL)" {} + 12 "INSERT INTO t2 VALUES(X'ABCDEF', NULL)" {} + + 13 "INSERT INTO t2 VALUES(NULL, NULL)" {} + 14 "INSERT INTO t2 VALUES(NULL, NULL)" {} +} + +# EVIDENCE-OF: R-61866-38053 Unless the column is an INTEGER PRIMARY KEY +# SQLite allows NULL values in a PRIMARY KEY column. +# +# If the column is an integer primary key, attempting to insert a NULL +# into the column triggers the auto-increment behaviour. Attempting +# to use UPDATE to set an ipk column to a NULL value is an error. +# do_createtable_tests 4.5.1 { - 1 "SELECT count(*) FROM t1 WHERE x IS NULL" 0 - 2 "SELECT count(*) FROM t2 WHERE x IS NULL" 0 - 3 "SELECT count(*) FROM t2 WHERE y IS NULL" 0 - 4 "SELECT count(*) FROM t2 WHERE x IS NULL AND y IS NULL" 0 + 1 "SELECT count(*) FROM t1 WHERE x IS NULL" 3 + 2 "SELECT count(*) FROM t2 WHERE x IS NULL" 6 + 3 "SELECT count(*) FROM t2 WHERE y IS NULL" 7 + 4 "SELECT count(*) FROM t2 WHERE x IS NULL AND y IS NULL" 2 } do_execsql_test 4.5.2 { CREATE TABLE t3(s, u INTEGER PRIMARY KEY, v); INSERT INTO t3 VALUES(1, NULL, 2); INSERT INTO t3 VALUES('x', NULL, 'y'); @@ -1261,11 +1273,11 @@ SELECT u FROM t3; } {1 2} do_catchsql_test 4.5.3 { INSERT INTO t3 VALUES(2, 5, 3); UPDATE t3 SET u = NULL WHERE s = 2; -} {1 {t3.u may not be NULL}} +} {1 {datatype mismatch}} # EVIDENCE-OF: R-00227-21080 A UNIQUE constraint is similar to a PRIMARY # KEY constraint, except that a single table may have any number of # UNIQUE constraints. # @@ -1338,15 +1350,15 @@ # index in the database (in the same way as a "CREATE UNIQUE INDEX" # statement would). do_createtable_tests 4.9 -repair drop_all_tables -query { SELECT count(*) FROM sqlite_master WHERE type='index' } { - 1 "CREATE TABLE t1(a TEXT PRIMARY KEY, b)" 0 + 1 "CREATE TABLE t1(a TEXT PRIMARY KEY, b)" 1 2 "CREATE TABLE t1(a INTEGER PRIMARY KEY, b)" 0 3 "CREATE TABLE t1(a TEXT UNIQUE, b)" 1 - 4 "CREATE TABLE t1(a PRIMARY KEY, b TEXT UNIQUE)" 1 - 5 "CREATE TABLE t1(a PRIMARY KEY, b, c, UNIQUE(c, b))" 1 + 4 "CREATE TABLE t1(a PRIMARY KEY, b TEXT UNIQUE)" 2 + 5 "CREATE TABLE t1(a PRIMARY KEY, b, c, UNIQUE(c, b))" 2 } # EVIDENCE-OF: R-02252-33116 Such an index is used like any other index # in the database to optimize queries. # @@ -1354,17 +1366,17 @@ CREATE TABLE t1(a, b PRIMARY KEY); CREATE TABLE t2(a, b, c, UNIQUE(b, c)); } do_createtable_tests 4.10 { 1 "EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b = 5" - {0 0 0 {SEARCH TABLE t1 USING PRIMARY KEY (b=?)}} + {0 0 0 {SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (b=?) (~1 rows)}} 2 "EXPLAIN QUERY PLAN SELECT * FROM t2 ORDER BY b, c" - {0 0 0 {SCAN TABLE t2 USING INDEX sqlite_t2_unique1}} + {0 0 0 {SCAN TABLE t2 USING INDEX sqlite_autoindex_t2_1 (~1000000 rows)}} 3 "EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE b=10 AND c>10" - {0 0 0 {SEARCH TABLE t2 USING INDEX sqlite_t2_unique1 (b=? AND c>?)}} + {0 0 0 {SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (b=? AND c>?) (~2 rows)}} } # EVIDENCE-OF: R-45493-35653 A CHECK constraint may be attached to a # column definition or specified as a table constraint. In practice it # makes no difference. @@ -1526,61 +1538,61 @@ INSERT INTO t3_re SELECT * FROM t3_ab; INSERT INTO t3_xx SELECT * FROM t3_ab; } foreach {tn tbl res ac data} { - 1 t1_ab {1 {PRIMARY KEY must be unique}} 0 {1 one 2 two 3 three} - 2 t1_ro {1 {PRIMARY KEY must be unique}} 1 {1 one 2 two} - 3 t1_fa {1 {PRIMARY KEY must be unique}} 0 {1 one 2 two 3 three 4 string} + 1 t1_ab {1 {column a is not unique}} 0 {1 one 2 two 3 three} + 2 t1_ro {1 {column a is not unique}} 1 {1 one 2 two} + 3 t1_fa {1 {column a is not unique}} 0 {1 one 2 two 3 three 4 string} 4 t1_ig {0 {}} 0 {1 one 2 two 3 three 4 string 6 string} - 5 t1_re {0 {}} 0 {1 one 2 two 3 string 4 string 6 string} - 6 t1_xx {1 {PRIMARY KEY must be unique}} 0 {1 one 2 two 3 three} + 5 t1_re {0 {}} 0 {1 one 2 two 4 string 3 string 6 string} + 6 t1_xx {1 {column a is not unique}} 0 {1 one 2 two 3 three} } { catchsql COMMIT do_execsql_test 4.15.$tn.1 "BEGIN; INSERT INTO $tbl VALUES(3, 'three')" do_catchsql_test 4.15.$tn.2 " INSERT INTO $tbl SELECT ((a%2)*a+3), 'string' FROM $tbl; " $res - do_test e_createtable-4.15.$tn.3 { sqlite4_db_transaction_status db } [expr !$ac] + do_test e_createtable-4.15.$tn.3 { sqlite4_get_autocommit db } $ac do_execsql_test 4.15.$tn.4 "SELECT * FROM $tbl" $data } -foreach {tn tbl res trans data} { - 1 t2_ab {1 {t2_ab.b may not be NULL}} 1 {1 one 2 two 3 three} - 2 t2_ro {1 {t2_ro.b may not be NULL}} 0 {1 one 2 two} - 3 t2_fa {1 {t2_fa.b may not be NULL}} 1 {1 one 2 two 3 three 4 xx} - 4 t2_ig {0 {}} 1 {1 one 2 two 3 three 4 xx 6 xx} - 5 t2_re {1 {t2_re.b may not be NULL}} 1 {1 one 2 two 3 three} - 6 t2_xx {1 {t2_xx.b may not be NULL}} 1 {1 one 2 two 3 three} +foreach {tn tbl res ac data} { + 1 t2_ab {1 {t2_ab.b may not be NULL}} 0 {1 one 2 two 3 three} + 2 t2_ro {1 {t2_ro.b may not be NULL}} 1 {1 one 2 two} + 3 t2_fa {1 {t2_fa.b may not be NULL}} 0 {1 one 2 two 3 three 4 xx} + 4 t2_ig {0 {}} 0 {1 one 2 two 3 three 4 xx 6 xx} + 5 t2_re {1 {t2_re.b may not be NULL}} 0 {1 one 2 two 3 three} + 6 t2_xx {1 {t2_xx.b may not be NULL}} 0 {1 one 2 two 3 three} } { catchsql COMMIT do_execsql_test 4.16.$tn.1 "BEGIN; INSERT INTO $tbl VALUES(3, 'three')" do_catchsql_test 4.16.$tn.2 " INSERT INTO $tbl SELECT a+3, CASE a WHEN 2 THEN NULL ELSE 'xx' END FROM $tbl " $res - do_test e_createtable-4.16.$tn.3 { sqlite4_db_transaction_status db } $trans + do_test e_createtable-4.16.$tn.3 { sqlite4_get_autocommit db } $ac do_execsql_test 4.16.$tn.4 "SELECT * FROM $tbl" $data } -foreach {tn tbl res trans data} { - 1 t3_ab {1 {columns a, b are not unique}} 1 {1 one 2 two 3 three} - 2 t3_ro {1 {columns a, b are not unique}} 0 {1 one 2 two} - 3 t3_fa {1 {columns a, b are not unique}} 1 {1 one 2 two 3 three 4 three} - 4 t3_ig {0 {}} 1 {1 one 2 two 3 three 4 three 6 three} - 5 t3_re {0 {}} 1 {1 one 2 two 4 three 3 three 6 three} - 6 t3_xx {1 {columns a, b are not unique}} 1 {1 one 2 two 3 three} +foreach {tn tbl res ac data} { + 1 t3_ab {1 {columns a, b are not unique}} 0 {1 one 2 two 3 three} + 2 t3_ro {1 {columns a, b are not unique}} 1 {1 one 2 two} + 3 t3_fa {1 {columns a, b are not unique}} 0 {1 one 2 two 3 three 4 three} + 4 t3_ig {0 {}} 0 {1 one 2 two 3 three 4 three 6 three} + 5 t3_re {0 {}} 0 {1 one 2 two 4 three 3 three 6 three} + 6 t3_xx {1 {columns a, b are not unique}} 0 {1 one 2 two 3 three} } { catchsql COMMIT do_execsql_test 4.17.$tn.1 "BEGIN; INSERT INTO $tbl VALUES(3, 'three')" do_catchsql_test 4.17.$tn.2 " INSERT INTO $tbl SELECT ((a%2)*a+3), 'three' FROM $tbl " $res - do_test e_createtable-4.17.$tn.3 { sqlite4_db_transaction_status db } $trans + do_test e_createtable-4.17.$tn.3 { sqlite4_get_autocommit db } $ac do_execsql_test 4.17.$tn.4 "SELECT * FROM $tbl" $data } catchsql COMMIT # EVIDENCE-OF: R-12645-39772 Or, if a constraint definition does not @@ -1599,11 +1611,11 @@ } do_execsql_test 4.18.2 { BEGIN; INSERT INTO t4 VALUES(5, 6) } do_catchsql_test 4.18.3 { INSERT INTO t4 SELECT a+4, b+4 FROM t4 } {1 {constraint failed}} -do_test e_createtable-4.18.4 { sqlite4_db_transaction_status db } 1 +do_test e_createtable-4.18.4 { sqlite4_get_autocommit db } 0 do_execsql_test 4.18.5 { SELECT * FROM t4 } {1 2 3 4 5 6} # EVIDENCE-OF: R-19114-56113 Different constraints within the same table # may have different default conflict resolution algorithms. # @@ -1614,10 +1626,102 @@ do_execsql_test 4.19.2 { SELECT * FROM t5 } {} do_catchsql_test 4.19.3 { INSERT INTO t5 VALUES('not null', NULL) } \ {1 {t5.b may not be NULL}} do_execsql_test 4.19.4 { SELECT * FROM t5 } {} +#------------------------------------------------------------------------ +# Tests for INTEGER PRIMARY KEY and rowid related statements. +# + +# EVIDENCE-OF: R-52584-04009 The rowid value can be accessed using one +# of the special case-independent names "rowid", "oid", or "_rowid_" in +# place of a column name. +# +drop_all_tables +do_execsql_test 5.1.0 { + CREATE TABLE t1(x, y); + INSERT INTO t1 VALUES('one', 'first'); + INSERT INTO t1 VALUES('two', 'second'); + INSERT INTO t1 VALUES('three', 'third'); +} +do_createtable_tests 5.1 { + 1 "SELECT rowid FROM t1" {1 2 3} + 2 "SELECT oid FROM t1" {1 2 3} + 3 "SELECT _rowid_ FROM t1" {1 2 3} + 4 "SELECT ROWID FROM t1" {1 2 3} + 5 "SELECT OID FROM t1" {1 2 3} + 6 "SELECT _ROWID_ FROM t1" {1 2 3} + 7 "SELECT RoWiD FROM t1" {1 2 3} + 8 "SELECT OiD FROM t1" {1 2 3} + 9 "SELECT _RoWiD_ FROM t1" {1 2 3} +} + +# EVIDENCE-OF: R-26501-17306 If a table contains a user defined column +# named "rowid", "oid" or "_rowid_", then that name always refers the +# explicitly declared column and cannot be used to retrieve the integer +# rowid value. +# +do_execsql_test 5.2.0 { + CREATE TABLE t2(oid, b); + CREATE TABLE t3(a, _rowid_); + CREATE TABLE t4(a, b, rowid); + + INSERT INTO t2 VALUES('one', 'two'); + INSERT INTO t2 VALUES('three', 'four'); + + INSERT INTO t3 VALUES('five', 'six'); + INSERT INTO t3 VALUES('seven', 'eight'); + + INSERT INTO t4 VALUES('nine', 'ten', 'eleven'); + INSERT INTO t4 VALUES('twelve', 'thirteen', 'fourteen'); +} +do_createtable_tests 5.2 { + 1 "SELECT oid, rowid, _rowid_ FROM t2" {one 1 1 three 2 2} + 2 "SELECT oid, rowid, _rowid_ FROM t3" {1 1 six 2 2 eight} + 3 "SELECT oid, rowid, _rowid_ FROM t4" {1 eleven 1 2 fourteen 2} +} + + +# Argument $tbl is the name of a table in the database. Argument $col is +# the name of one of the tables columns. Return 1 if $col is an alias for +# the rowid, or 0 otherwise. +# +proc is_integer_primary_key {tbl col} { + lindex [db eval [subst { + DELETE FROM $tbl; + INSERT INTO $tbl ($col) VALUES(0); + SELECT (rowid==$col) FROM $tbl; + DELETE FROM $tbl; + }]] 0 +} + +# EVIDENCE-OF: R-53738-31673 With one exception, if a table has a +# primary key that consists of a single column, and the declared type of +# that column is "INTEGER" in any mixture of upper and lower case, then +# the column becomes an alias for the rowid. +# +# EVIDENCE-OF: R-45951-08347 if the declaration of a column with +# declared type "INTEGER" includes an "PRIMARY KEY DESC" clause, it does +# not become an alias for the rowid and is not classified as an integer +# primary key. +# +do_createtable_tests 5.3 -tclquery { + is_integer_primary_key t5 pk +} -repair { + catchsql { DROP TABLE t5 } +} { + 1 "CREATE TABLE t5(pk integer primary key)" 1 + 2 "CREATE TABLE t5(pk integer, primary key(pk))" 1 + 3 "CREATE TABLE t5(pk integer, v integer, primary key(pk))" 1 + 4 "CREATE TABLE t5(pk integer, v integer, primary key(pk, v))" 0 + 5 "CREATE TABLE t5(pk int, v integer, primary key(pk, v))" 0 + 6 "CREATE TABLE t5(pk int, v integer, primary key(pk))" 0 + 7 "CREATE TABLE t5(pk int primary key, v integer)" 0 + 8 "CREATE TABLE t5(pk inTEger primary key)" 1 + 9 "CREATE TABLE t5(pk inteGEr, primary key(pk))" 1 + 10 "CREATE TABLE t5(pk INTEGER, v integer, primary key(pk))" 1 +} # EVIDENCE-OF: R-41444-49665 Other integer type names like "INT" or # "BIGINT" or "SHORT INTEGER" or "UNSIGNED INTEGER" causes the primary # key column to behave as an ordinary table column with integer affinity # and a unique index, not as an alias for the rowid. @@ -1626,10 +1730,14 @@ CREATE TABLE t6(pk INT primary key); CREATE TABLE t7(pk BIGINT primary key); CREATE TABLE t8(pk SHORT INTEGER primary key); CREATE TABLE t9(pk UNSIGNED INTEGER primary key); } +do_test e_createtable-5.4.2.1 { is_integer_primary_key t6 pk } 0 +do_test e_createtable-5.4.2.2 { is_integer_primary_key t7 pk } 0 +do_test e_createtable-5.4.2.3 { is_integer_primary_key t8 pk } 0 +do_test e_createtable-5.4.2.4 { is_integer_primary_key t9 pk } 0 do_execsql_test 5.4.3 { INSERT INTO t6 VALUES('2.0'); INSERT INTO t7 VALUES('2.0'); INSERT INTO t8 VALUES('2.0'); @@ -1640,17 +1748,178 @@ SELECT typeof(pk), pk FROM t9; } {integer 2 integer 2 integer 2 integer 2} do_catchsql_test 5.4.4.1 { INSERT INTO t6 VALUES(2) -} {1 {PRIMARY KEY must be unique}} +} {1 {column pk is not unique}} do_catchsql_test 5.4.4.2 { INSERT INTO t7 VALUES(2) -} {1 {PRIMARY KEY must be unique}} +} {1 {column pk is not unique}} do_catchsql_test 5.4.4.3 { INSERT INTO t8 VALUES(2) -} {1 {PRIMARY KEY must be unique}} +} {1 {column pk is not unique}} do_catchsql_test 5.4.4.4 { INSERT INTO t9 VALUES(2) -} {1 {PRIMARY KEY must be unique}} +} {1 {column pk is not unique}} + +# EVIDENCE-OF: R-56094-57830 the following three table declarations all +# cause the column "x" to be an alias for the rowid (an integer primary +# key): CREATE TABLE t(x INTEGER PRIMARY KEY ASC, y, z); CREATE TABLE +# t(x INTEGER, y, z, PRIMARY KEY(x ASC)); CREATE TABLE t(x INTEGER, y, +# z, PRIMARY KEY(x DESC)); +# +# EVIDENCE-OF: R-20149-25884 the following declaration does not result +# in "x" being an alias for the rowid: CREATE TABLE t(x INTEGER PRIMARY +# KEY DESC, y, z); +# +do_createtable_tests 5 -tclquery { + is_integer_primary_key t x +} -repair { + catchsql { DROP TABLE t } +} { + 5.1 "CREATE TABLE t(x INTEGER PRIMARY KEY ASC, y, z)" 1 + 5.2 "CREATE TABLE t(x INTEGER, y, z, PRIMARY KEY(x ASC))" 1 + 5.3 "CREATE TABLE t(x INTEGER, y, z, PRIMARY KEY(x DESC))" 1 + 6.1 "CREATE TABLE t(x INTEGER PRIMARY KEY DESC, y, z)" 0 +} + +# EVIDENCE-OF: R-03733-29734 Rowid values may be modified using an +# UPDATE statement in the same way as any other column value can, either +# using one of the built-in aliases ("rowid", "oid" or "_rowid_") or by +# using an alias created by an integer primary key. +# +do_execsql_test 5.7.0 { + CREATE TABLE t10(a, b); + INSERT INTO t10 VALUES('ten', 10); + + CREATE TABLE t11(a, b INTEGER PRIMARY KEY); + INSERT INTO t11 VALUES('ten', 10); +} +do_createtable_tests 5.7.1 -query { + SELECT rowid, _rowid_, oid FROM t10; +} { + 1 "UPDATE t10 SET rowid = 5" {5 5 5} + 2 "UPDATE t10 SET _rowid_ = 6" {6 6 6} + 3 "UPDATE t10 SET oid = 7" {7 7 7} +} +do_createtable_tests 5.7.2 -query { + SELECT rowid, _rowid_, oid, b FROM t11; +} { + 1 "UPDATE t11 SET rowid = 5" {5 5 5 5} + 2 "UPDATE t11 SET _rowid_ = 6" {6 6 6 6} + 3 "UPDATE t11 SET oid = 7" {7 7 7 7} + 4 "UPDATE t11 SET b = 8" {8 8 8 8} +} + +# EVIDENCE-OF: R-58706-14229 Similarly, an INSERT statement may provide +# a value to use as the rowid for each row inserted. +# +do_createtable_tests 5.8.1 -query { + SELECT rowid, _rowid_, oid FROM t10; +} -repair { + execsql { DELETE FROM t10 } +} { + 1 "INSERT INTO t10(oid) VALUES(15)" {15 15 15} + 2 "INSERT INTO t10(rowid) VALUES(16)" {16 16 16} + 3 "INSERT INTO t10(_rowid_) VALUES(17)" {17 17 17} + 4 "INSERT INTO t10(a, b, oid) VALUES(1,2,3)" {3 3 3} +} +do_createtable_tests 5.8.2 -query { + SELECT rowid, _rowid_, oid, b FROM t11; +} -repair { + execsql { DELETE FROM t11 } +} { + 1 "INSERT INTO t11(oid) VALUES(15)" {15 15 15 15} + 2 "INSERT INTO t11(rowid) VALUES(16)" {16 16 16 16} + 3 "INSERT INTO t11(_rowid_) VALUES(17)" {17 17 17 17} + 4 "INSERT INTO t11(a, b) VALUES(1,2)" {2 2 2 2} +} + +# EVIDENCE-OF: R-32326-44592 Unlike normal SQLite columns, an integer +# primary key or rowid column must contain integer values. Integer +# primary key or rowid columns are not able to hold floating point +# values, strings, BLOBs, or NULLs. +# +# This is considered by the tests for the following 3 statements, +# which show that: +# +# 1. Attempts to UPDATE a rowid column to a non-integer value fail, +# 2. Attempts to INSERT a real, string or blob value into a rowid +# column fail, and +# 3. Attempting to INSERT a NULL value into a rowid column causes the +# system to automatically select an integer value to use. +# + + +# EVIDENCE-OF: R-64224-62578 If an UPDATE statement attempts to set an +# integer primary key or rowid column to a NULL or blob value, or to a +# string or real value that cannot be losslessly converted to an +# integer, a "datatype mismatch" error occurs and the statement is +# aborted. +# +drop_all_tables +do_execsql_test 5.9.0 { + CREATE TABLE t12(x INTEGER PRIMARY KEY, y); + INSERT INTO t12 VALUES(5, 'five'); +} +do_createtable_tests 5.9.1 -query { SELECT typeof(x), x FROM t12 } { + 1 "UPDATE t12 SET x = 4" {integer 4} + 2 "UPDATE t12 SET x = 10.0" {integer 10} + 3 "UPDATE t12 SET x = '12.0'" {integer 12} + 4 "UPDATE t12 SET x = '-15.0'" {integer -15} +} +do_createtable_tests 5.9.2 -error { + datatype mismatch +} { + 1 "UPDATE t12 SET x = 4.1" {} + 2 "UPDATE t12 SET x = 'hello'" {} + 3 "UPDATE t12 SET x = NULL" {} + 4 "UPDATE t12 SET x = X'ABCD'" {} + 5 "UPDATE t12 SET x = X'3900'" {} + 6 "UPDATE t12 SET x = X'39'" {} +} + +# EVIDENCE-OF: R-05734-13629 If an INSERT statement attempts to insert a +# blob value, or a string or real value that cannot be losslessly +# converted to an integer into an integer primary key or rowid column, a +# "datatype mismatch" error occurs and the statement is aborted. +# +do_execsql_test 5.10.0 { DELETE FROM t12 } +do_createtable_tests 5.10.1 -error { + datatype mismatch +} { + 1 "INSERT INTO t12(x) VALUES(4.1)" {} + 2 "INSERT INTO t12(x) VALUES('hello')" {} + 3 "INSERT INTO t12(x) VALUES(X'ABCD')" {} + 4 "INSERT INTO t12(x) VALUES(X'3900')" {} + 5 "INSERT INTO t12(x) VALUES(X'39')" {} +} +do_createtable_tests 5.10.2 -query { + SELECT typeof(x), x FROM t12 +} -repair { + execsql { DELETE FROM t12 } +} { + 1 "INSERT INTO t12(x) VALUES(4)" {integer 4} + 2 "INSERT INTO t12(x) VALUES(10.0)" {integer 10} + 3 "INSERT INTO t12(x) VALUES('12.0')" {integer 12} + 4 "INSERT INTO t12(x) VALUES('4e3')" {integer 4000} + 5 "INSERT INTO t12(x) VALUES('-14.0')" {integer -14} +} + +# EVIDENCE-OF: R-07986-46024 If an INSERT statement attempts to insert a +# NULL value into a rowid or integer primary key column, the system +# chooses an integer value to use as the rowid automatically. +# +do_execsql_test 5.11.0 { DELETE FROM t12 } +do_createtable_tests 5.11 -query { + SELECT typeof(x), x FROM t12 WHERE y IS (SELECT max(y) FROM t12) +} { + 1 "INSERT INTO t12 DEFAULT VALUES" {integer 1} + 2 "INSERT INTO t12(y) VALUES(5)" {integer 2} + 3 "INSERT INTO t12(x,y) VALUES(NULL, 10)" {integer 3} + 4 "INSERT INTO t12(x,y) SELECT NULL, 15 FROM t12" + {integer 4 integer 5 integer 6} + 5 "INSERT INTO t12(y) SELECT 20 FROM t12 LIMIT 3" + {integer 7 integer 8 integer 9} +} finish_test Index: test/e_delete.test ================================================================== --- test/e_delete.test +++ test/e_delete.test @@ -204,12 +204,12 @@ # attached). # do_execsql_test e_delete-2.3.0 { DROP TRIGGER aux.tr1; DROP TRIGGER main.tr1; - DELETE FROM main.t8 WHERE rowid>1; - DELETE FROM aux.t8 WHERE rowid>1; + DELETE FROM main.t8 WHERE oid>1; + DELETE FROM aux.t8 WHERE oid>1; INSERT INTO aux.t9 VALUES(1, 2); INSERT INTO main.t7 VALUES(3, 4); } {} do_execsql_test e_delete-2.3.1 { SELECT count(*) FROM temp.t7 UNION ALL SELECT count(*) FROM main.t7 UNION ALL Index: test/e_expr.test ================================================================== --- test/e_expr.test +++ test/e_expr.test @@ -42,11 +42,11 @@ foreach {op opn} { || cat * mul / div % mod + add - sub << lshift >> rshift & bitand | bitor < less <= lesseq > more >= moreeq = eq1 == eq2 <> ne1 != ne2 IS is LIKE like - GLOB glob AND and OR or REGEXP regexp + GLOB glob AND and OR or MATCH match REGEXP regexp {IS NOT} isnt } { set ::opname($op) $opn } set oplist [list] @@ -54,11 +54,11 @@ 1 || 2 {* / %} 3 {+ -} 4 {<< >> & |} 5 {< <= > >=} - 6 {= == != <> IS {IS NOT} LIKE GLOB REGEXP} + 6 {= == != <> IS {IS NOT} LIKE GLOB MATCH REGEXP} 7 AND 8 OR } { foreach op $opl { set ::opprec($op) $prec @@ -196,11 +196,11 @@ foreach {tn literal type} { 1 'helloworld' text 2 45 integer 3 45.2 real 4 45.0 real - 5 x'abcdef' blob + 5 X'ABCDEF' blob 6 NULL null } { set sql " SELECT quote( + $literal ), typeof( + $literal) " do_execsql_test e_expr-3.$tn $sql [list $literal $type] } @@ -735,10 +735,12 @@ 55 "EXPR1 LIKE EXPR2 ESCAPE EXPR" 56 "EXPR1 GLOB EXPR2" 57 "EXPR1 GLOB EXPR2 ESCAPE EXPR" 58 "EXPR1 REGEXP EXPR2" 59 "EXPR1 REGEXP EXPR2 ESCAPE EXPR" + 60 "EXPR1 MATCH EXPR2" + 61 "EXPR1 MATCH EXPR2 ESCAPE EXPR" 62 "EXPR1 NOT LIKE EXPR2" 63 "EXPR1 NOT LIKE EXPR2 ESCAPE EXPR" 64 "EXPR1 NOT GLOB EXPR2" 65 "EXPR1 NOT GLOB EXPR2 ESCAPE EXPR" 66 "EXPR1 NOT REGEXP EXPR2" @@ -1089,10 +1091,39 @@ do_test e_expr-18.2.2 { set regexpargs } {def abc} set ::regexpargs [list] do_execsql_test e_expr-18.2.3 { SELECT 'X' NOT REGEXP 'Y' } 0 do_test e_expr-18.2.4 { set regexpargs } {Y X} sqlite4 db test.db + +# EVIDENCE-OF: R-42037-37826 The default match() function implementation +# raises an exception and is not really useful for anything. +# +do_catchsql_test e_expr-19.1.1 { + SELECT 'abc' MATCH 'def' +} {1 {unable to use function MATCH in the requested context}} +do_catchsql_test e_expr-19.1.2 { + SELECT match('abc', 'def') +} {1 {unable to use function MATCH in the requested context}} + +# EVIDENCE-OF: R-37916-47407 The MATCH operator is a special syntax for +# the match() application-defined function. +# +# EVIDENCE-OF: R-06021-09373 But extensions can override the match() +# function with more helpful logic. +# +proc matchfunc {args} { + eval lappend ::matchargs $args + return 1 +} +db func match -argcount 2 matchfunc +set ::matchargs [list] +do_execsql_test e_expr-19.2.1 { SELECT 'abc' MATCH 'def' } 1 +do_test e_expr-19.2.2 { set matchargs } {def abc} +set ::matchargs [list] +do_execsql_test e_expr-19.2.3 { SELECT 'X' NOT MATCH 'Y' } 0 +do_test e_expr-19.2.4 { set matchargs } {Y X} +sqlite4 db test.db #------------------------------------------------------------------------- # Test cases for the testable statements related to the CASE expression. # # EVIDENCE-OF: R-15199-61389 There are two basic forms of the CASE @@ -1280,11 +1311,11 @@ do_execsql_test e_expr-23.1.4 { SELECT CASE a WHEN b THEN 'A' ELSE 'B' END FROM t1 } {B} do_execsql_test e_expr-23.1.5 { SELECT CASE b WHEN a THEN 'A' ELSE 'B' END FROM t1 -} {B} +} {A} do_execsql_test e_expr-23.1.6 { SELECT CASE 55 WHEN '55' THEN 'A' ELSE 'B' END } {B} do_execsql_test e_expr-23.1.7 { SELECT CASE c WHEN '55' THEN 'A' ELSE 'B' END FROM t1 @@ -1406,28 +1437,28 @@ # EVIDENCE-OF: R-22956-37754 Casting to a BLOB consists of first casting # the value to TEXT in the encoding of the database connection, then # interpreting the resulting byte sequence as a BLOB instead of as TEXT. # -do_qexpr_test e_expr-27.4.1 { CAST('ghi' AS blob) } x'676869' -do_qexpr_test e_expr-27.4.2 { CAST(456 AS blob) } x'343536' -do_qexpr_test e_expr-27.4.3 { CAST(1.78 AS blob) } x'312e3738' +do_qexpr_test e_expr-27.4.1 { CAST('ghi' AS blob) } X'676869' +do_qexpr_test e_expr-27.4.2 { CAST(456 AS blob) } X'343536' +do_qexpr_test e_expr-27.4.3 { CAST(1.78 AS blob) } X'312E3738' rename db db2 sqlite4 db :memory: ifcapable {utf16} { db eval { PRAGMA encoding = 'utf-16le' } -do_qexpr_test e_expr-27.4.4 { CAST('ghi' AS blob) } x'670068006900' -do_qexpr_test e_expr-27.4.5 { CAST(456 AS blob) } x'340035003600' -do_qexpr_test e_expr-27.4.6 { CAST(1.78 AS blob) } x'31002e0037003800' +do_qexpr_test e_expr-27.4.4 { CAST('ghi' AS blob) } X'670068006900' +do_qexpr_test e_expr-27.4.5 { CAST(456 AS blob) } X'340035003600' +do_qexpr_test e_expr-27.4.6 { CAST(1.78 AS blob) } X'31002E0037003800' } db close sqlite4 db :memory: db eval { PRAGMA encoding = 'utf-16be' } ifcapable {utf16} { -do_qexpr_test e_expr-27.4.7 { CAST('ghi' AS blob) } x'006700680069' -do_qexpr_test e_expr-27.4.8 { CAST(456 AS blob) } x'003400350036' -do_qexpr_test e_expr-27.4.9 { CAST(1.78 AS blob) } x'0031002e00370038' +do_qexpr_test e_expr-27.4.7 { CAST('ghi' AS blob) } X'006700680069' +do_qexpr_test e_expr-27.4.8 { CAST(456 AS blob) } X'003400350036' +do_qexpr_test e_expr-27.4.9 { CAST(1.78 AS blob) } X'0031002E00370038' } db close rename db2 db # EVIDENCE-OF: R-04207-37981 To cast a BLOB value to TEXT, the sequence @@ -1453,13 +1484,13 @@ do_expr_test e_expr-28.2.1 { CAST (1 AS text) } text 1 do_expr_test e_expr-28.2.2 { CAST (45 AS text) } text 45 do_expr_test e_expr-28.2.3 { CAST (-45 AS text) } text -45 do_expr_test e_expr-28.2.4 { CAST (8.8 AS text) } text 8.8 do_expr_test e_expr-28.2.5 { CAST (2.3e+5 AS text) } text 230000.0 -do_expr_test e_expr-28.2.6 { CAST (-2.3e-5 AS text) } text -0.000023 +do_expr_test e_expr-28.2.6 { CAST (-2.3e-5 AS text) } text -2.3e-05 do_expr_test e_expr-28.2.7 { CAST (0.0 AS text) } text 0.0 -do_expr_test e_expr-28.2.8 { CAST (0 AS text) } text 0 +do_expr_test e_expr-28.2.7 { CAST (0 AS text) } text 0 # EVIDENCE-OF: R-26346-36443 When casting a BLOB value to a REAL, the # value is first converted to TEXT. # do_expr_test e_expr-29.1.1 { CAST (X'312E3233' AS REAL) } real 1.23 @@ -1569,18 +1600,18 @@ # EVIDENCE-OF: R-49503-28105 If a REAL is too large to be represented as # an INTEGER then the result of the cast is the largest negative # integer: -9223372036854775808. # -do_expr_test e_expr-31.2.1 { CAST(2e+50 AS INT) } integer 9223372036854775807 +do_expr_test e_expr-31.2.1 { CAST(2e+50 AS INT) } integer -9223372036854775808 do_expr_test e_expr-31.2.2 { CAST(-2e+50 AS INT) } integer -9223372036854775808 do_expr_test e_expr-31.2.3 { CAST(-9223372036854775809.0 AS INT) } integer -9223372036854775808 do_expr_test e_expr-31.2.4 { CAST(9223372036854775809.0 AS INT) -} integer 9223372036854775807 +} integer -9223372036854775808 # EVIDENCE-OF: R-09295-61337 Casting a TEXT or BLOB value into NUMERIC # first does a forced conversion into REAL but then further converts the # result into INTEGER if and only if the conversion from REAL to INTEGER Index: test/e_fkey.test ================================================================== --- test/e_fkey.test +++ test/e_fkey.test @@ -127,11 +127,19 @@ ifcapable !foreignkey||!trigger { finish_test ; return } reset_db #------------------------------------------------------------------------- -# Update for src4: foreign-keys are on by default. +# EVIDENCE-OF: R-07280-60510 Assuming the library is compiled with +# foreign key constraints enabled, it must still be enabled by the +# application at runtime, using the PRAGMA foreign_keys command. +# +# This also tests that foreign key constraints are disabled by default. +# +# EVIDENCE-OF: R-59578-04990 Foreign key constraints are disabled by +# default (for backwards compatibility), so must be enabled separately +# for each database connection separately. # drop_all_tables do_test e_fkey-4.1 { execsql { CREATE TABLE p(i PRIMARY KEY); @@ -139,11 +147,11 @@ INSERT INTO p VALUES('hello'); INSERT INTO c VALUES('hello'); UPDATE p SET i = 'world'; SELECT * FROM c; } -} {world} +} {hello} do_test e_fkey-4.2 { execsql { DELETE FROM c; DELETE FROM p; PRAGMA foreign_keys = ON; @@ -164,11 +172,11 @@ # EVIDENCE-OF: R-11255-19907 # reset_db do_test e_fkey-5.1 { execsql { PRAGMA foreign_keys } -} {1} +} {0} do_test e_fkey-5.2 { execsql { PRAGMA foreign_keys = ON; PRAGMA foreign_keys; } @@ -549,11 +557,11 @@ } {} do_test e_fkey-16.3 { catchsql { UPDATE t2 SET b = 'two' WHERE rowid = 1 } } {1 {foreign key constraint failed}} do_test e_fkey-16.4 { - catchsql { DELETE FROM t1 WHERE a = 'oNe' } + catchsql { DELETE FROM t1 WHERE rowid = 1 } } {1 {foreign key constraint failed}} #------------------------------------------------------------------------- # Specifically, test that when comparing child and parent key values the # affinity of the parent key column is applied to the child key value @@ -581,11 +589,11 @@ } {2.0 text} do_test e_fkey-17.3 { execsql { SELECT typeof(a) FROM t1 } } {integer integer text} do_test e_fkey-17.4 { - catchsql { DELETE FROM t1 WHERE a = 2 } + catchsql { DELETE FROM t1 WHERE rowid = 2 } } {1 {foreign key constraint failed}} ########################################################################### ### SECTION 3: Required and Suggested Database Indexes ########################################################################### @@ -963,19 +971,19 @@ do_execsql_test e_fkey-25.2 { PRAGMA foreign_keys = OFF; EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1; EXPLAIN QUERY PLAN SELECT rowid FROM track WHERE trackartist = ?; } { - 0 0 0 {SCAN TABLE artist} - 0 0 0 {SCAN TABLE track} + 0 0 0 {SCAN TABLE artist (~1000000 rows)} + 0 0 0 {SCAN TABLE track (~100000 rows)} } do_execsql_test e_fkey-25.3 { PRAGMA foreign_keys = ON; EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1; } { - 0 0 0 {SCAN TABLE artist} - 0 0 0 {SCAN TABLE track} + 0 0 0 {SCAN TABLE artist (~1000000 rows)} + 0 0 0 {SCAN TABLE track (~100000 rows)} } do_test e_fkey-25.4 { execsql { INSERT INTO artist VALUES(5, 'artist 5'); INSERT INTO artist VALUES(6, 'artist 6'); @@ -1088,19 +1096,19 @@ eqp { INSERT INTO artist VALUES(?, ?) } } {} do_execsql_test e_fkey-27.3 { EXPLAIN QUERY PLAN UPDATE artist SET artistid = ?, artistname = ? } { - 0 0 0 {SCAN TABLE artist} - 0 0 0 {SEARCH TABLE track USING INDEX trackindex (trackartist=?)} - 0 0 0 {SEARCH TABLE track USING INDEX trackindex (trackartist=?)} + 0 0 0 {SCAN TABLE artist (~1000000 rows)} + 0 0 0 {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?) (~10 rows)} + 0 0 0 {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?) (~10 rows)} } do_execsql_test e_fkey-27.4 { EXPLAIN QUERY PLAN DELETE FROM artist } { - 0 0 0 {SCAN TABLE artist} - 0 0 0 {SEARCH TABLE track USING INDEX trackindex (trackartist=?)} + 0 0 0 {SCAN TABLE artist (~1000000 rows)} + 0 0 0 {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?) (~10 rows)} } ########################################################################### ### SECTION 4.1: Composite Foreign Key Constraints @@ -2005,25 +2013,25 @@ INSERT INTO cB VALUES(X'1234'); } } {} do_test e_fkey-44.2 { execsql { - DELETE FROM pA WHERE x = x'abcd'; + DELETE FROM pA WHERE rowid = 1; SELECT quote(x) FROM pA; } -} {x'1234'} +} {X'1234'} do_test e_fkey-44.3 { execsql { SELECT quote(c) FROM cA; } } {NULL} do_test e_fkey-44.4 { execsql { - UPDATE pA SET x = X'8765' WHERE x = X'1234'; + UPDATE pA SET x = X'8765' WHERE rowid = 2; SELECT quote(x) FROM pA; } -} {x'8765'} +} {X'8765'} do_test e_fkey-44.5 { execsql { SELECT quote(c) FROM cB } } {NULL} #------------------------------------------------------------------------- @@ -2038,37 +2046,37 @@ execsql { CREATE TABLE pA(x PRIMARY KEY); CREATE TABLE cA(c DEFAULT X'0000' REFERENCES pA ON DELETE SET DEFAULT); CREATE TABLE cB(c DEFAULT X'9999' REFERENCES pA ON UPDATE SET DEFAULT); - INSERT INTO pA(x) VALUES(X'0000'); - INSERT INTO pA(x) VALUES(X'9999'); - INSERT INTO pA(x) VALUES(X'ABCD'); - INSERT INTO pA(x) VALUES(X'1234'); + INSERT INTO pA(rowid, x) VALUES(1, X'0000'); + INSERT INTO pA(rowid, x) VALUES(2, X'9999'); + INSERT INTO pA(rowid, x) VALUES(3, X'ABCD'); + INSERT INTO pA(rowid, x) VALUES(4, X'1234'); INSERT INTO cA VALUES(X'ABCD'); INSERT INTO cB VALUES(X'1234'); } } {} do_test e_fkey-45.2 { execsql { - DELETE FROM pA WHERE x = X'ABCD'; + DELETE FROM pA WHERE rowid = 3; SELECT quote(x) FROM pA; } -} {x'0000' x'1234' x'9999'} +} {X'0000' X'9999' X'1234'} do_test e_fkey-45.3 { execsql { SELECT quote(c) FROM cA } -} {x'0000'} +} {X'0000'} do_test e_fkey-45.4 { execsql { - UPDATE pA SET x = X'8765' WHERE x = X'1234'; + UPDATE pA SET x = X'8765' WHERE rowid = 4; SELECT quote(x) FROM pA; } -} {x'0000' x'8765' x'9999'} +} {X'0000' X'9999' X'8765'} do_test e_fkey-45.5 { execsql { SELECT quote(c) FROM cB } -} {x'9999'} +} {X'9999'} #------------------------------------------------------------------------- # Test ON DELETE CASCADE actions. # # EVIDENCE-OF: R-61376-57267 A "CASCADE" action propagates the delete or @@ -2317,21 +2325,21 @@ do_test e_fkey-51.2 { execsql { UPDATE parent SET x = 22; SELECT * FROM parent UNION ALL SELECT 'xxx' UNION ALL SELECT a FROM child; } -} {21 22 23 xxx 22} +} {22 21 23 xxx 22} do_test e_fkey-51.3 { execsql { DELETE FROM child; DELETE FROM parent; INSERT INTO parent VALUES(-1); INSERT INTO child VALUES(-1); UPDATE parent SET x = 22; SELECT * FROM parent UNION ALL SELECT 'xxx' UNION ALL SELECT a FROM child; } -} {21 22 23 xxx 23} +} {22 23 21 xxx 23} #------------------------------------------------------------------------- # Verify that ON UPDATE actions only actually take place if the parent key # is set to a new value that is distinct from the old value. The default @@ -2381,14 +2389,14 @@ SELECT typeof(c), c, typeof(d), d FROM apollo; } } {integer 1 text 1} do_test e_fkey-52.6 { execsql { - UPDATE zeus SET b = x'1234'; - SELECT typeof(c), c, typeof(d), quote(d) FROM apollo; + UPDATE zeus SET b = NULL; + SELECT typeof(c), c, typeof(d), d FROM apollo; } -} {integer 1 blob x'1234'} +} {integer 1 null {}} #------------------------------------------------------------------------- # EVIDENCE-OF: R-35129-58141 # # Test an example from the "ON DELETE and ON UPDATE Actions" section @@ -2576,11 +2584,11 @@ DEFERRABLE INITIALLY DEFERRED ); CREATE TABLE log(msg); CREATE TRIGGER tt AFTER DELETE ON p BEGIN - INSERT INTO log VALUES('delete ' || old.a || '|' || old.b); + INSERT INTO log VALUES('delete ' || old.rowid); END; } } {} do_test e_fkey-57.2 { @@ -2611,11 +2619,11 @@ BEGIN; DELETE FROM p; SELECT * FROM log; ROLLBACK; } -} {{delete a|b}} +} {{delete 1}} #------------------------------------------------------------------------- # If an IMMEDIATE foreign key fails as a result of a DROP TABLE, the # DROP TABLE command fails. # @@ -2708,10 +2716,17 @@ } {} do_test e_fkey-60.2 { execsql { PRAGMA foreign_keys = ON } catchsql { DELETE FROM p } } {1 {no such table: main.nosuchtable}} + + +breakpoint +execsql { PRAGMA trace = 1 } +execsql { DROP TABLE p } +execsql { PRAGMA trace = 0 } + do_test e_fkey-60.3 { execsql { BEGIN; DROP TABLE p; Index: test/e_insert.test ================================================================== --- test/e_insert.test +++ test/e_insert.test @@ -157,17 +157,17 @@ # column of the new row, and so on. # delete_all_data do_insert_tests e_insert-1.3 { 1a "INSERT INTO a2 VALUES(1, 2, 3)" {} - 1b "SELECT * FROM a2 WHERE rowid=(SELECT max(rowid) FROM a2)" {1 2 3} + 1b "SELECT * FROM a2 WHERE oid=last_insert_rowid()" {1 2 3} 2a "INSERT INTO a2 VALUES('abc', NULL, 3*3+1)" {} - 2b "SELECT * FROM a2 WHERE rowid=(SELECT max(rowid) FROM a2)" {abc {} 10} + 2b "SELECT * FROM a2 WHERE oid=last_insert_rowid()" {abc {} 10} 3a "INSERT INTO a2 VALUES((SELECT count(*) FROM a2), 'x', 'y')" {} - 3b "SELECT * FROM a2 WHERE rowid=(SELECT max(rowid) FROM a2)" {2 x y} + 3b "SELECT * FROM a2 WHERE oid=last_insert_rowid()" {2 x y} } # EVIDENCE-OF: R-62524-00361 If a column-list is specified, then the # number of values must match the number of specified columns. # @@ -344,32 +344,32 @@ do_execsql_test e_insert-4.1.0 { INSERT INTO a4 VALUES(1, 'a'); INSERT INTO a4 VALUES(2, 'a'); INSERT INTO a4 VALUES(3, 'a'); } {} -foreach {tn sql error ts data } { - 1.1 "INSERT INTO a4 VALUES(2,'b')" {column c is not unique} 0 {1 a 2 a 3 a} - 1.2 "INSERT OR REPLACE INTO a4 VALUES(2, 'b')" {} 0 {1 a 3 a 2 b} - 1.3 "INSERT OR IGNORE INTO a4 VALUES(3, 'c')" {} 0 {1 a 3 a 2 b} - 1.4 "BEGIN" {} 1 {1 a 3 a 2 b} - 1.5 "INSERT INTO a4 VALUES(1, 'd')" {column c is not unique} 1 {1 a 3 a 2 b} +foreach {tn sql error ac data } { + 1.1 "INSERT INTO a4 VALUES(2,'b')" {column c is not unique} 1 {1 a 2 a 3 a} + 1.2 "INSERT OR REPLACE INTO a4 VALUES(2, 'b')" {} 1 {1 a 3 a 2 b} + 1.3 "INSERT OR IGNORE INTO a4 VALUES(3, 'c')" {} 1 {1 a 3 a 2 b} + 1.4 "BEGIN" {} 0 {1 a 3 a 2 b} + 1.5 "INSERT INTO a4 VALUES(1, 'd')" {column c is not unique} 0 {1 a 3 a 2 b} 1.6 "INSERT OR ABORT INTO a4 VALUES(1, 'd')" - {column c is not unique} 1 {1 a 3 a 2 b} + {column c is not unique} 0 {1 a 3 a 2 b} 1.7 "INSERT OR ROLLBACK INTO a4 VALUES(1, 'd')" - {column c is not unique} 0 {1 a 3 a 2 b} + {column c is not unique} 1 {1 a 3 a 2 b} 1.8 "INSERT INTO a4 SELECT 4, 'e' UNION ALL SELECT 3, 'e'" - {column c is not unique} 0 {1 a 3 a 2 b} + {column c is not unique} 1 {1 a 3 a 2 b} 1.9 "INSERT OR FAIL INTO a4 SELECT 4, 'e' UNION ALL SELECT 3, 'e'" - {column c is not unique} 0 {1 a 3 a 2 b 4 e} + {column c is not unique} 1 {1 a 3 a 2 b 4 e} 2.1 "INSERT INTO a4 VALUES(2,'f')" - {column c is not unique} 0 {1 a 3 a 2 b 4 e} - 2.2 "REPLACE INTO a4 VALUES(2, 'f')" {} 0 {1 a 3 a 4 e 2 f} + {column c is not unique} 1 {1 a 3 a 2 b 4 e} + 2.2 "REPLACE INTO a4 VALUES(2, 'f')" {} 1 {1 a 3 a 4 e 2 f} } { do_catchsql_test e_insert-4.1.$tn.1 $sql [list [expr {$error!=""}] $error] do_execsql_test e_insert-4.1.$tn.2 {SELECT * FROM a4} [list {*}$data] - do_test e_insert-4.1.$tn.3 {sqlite4_db_transaction_status db} $ts + do_test e_insert-4.1.$tn.3 {sqlite4_get_autocommit db} $ac } # EVIDENCE-OF: R-64196-02418 The optional "database-name." prefix on the # table-name is support for top-level INSERT statements only. # Index: test/e_reindex.test ================================================================== --- test/e_reindex.test +++ test/e_reindex.test @@ -64,18 +64,18 @@ db close sqlite4 db test.db do_execsql_test e_reindex-1.3 { PRAGMA integrity_check; -} {{6 errors: -entry missing from index i2: 041810180e1808 -entry missing from index i1: 03180e18101808 -entry missing from index i2: 0418141812180a -entry missing from index i1: 0318121814180a -wrong # number of entries in index i2 -wrong # number of entries in index i1 -}} +} [list \ + {rowid 4 missing from index i2} \ + {rowid 4 missing from index i1} \ + {rowid 5 missing from index i2} \ + {rowid 5 missing from index i1} \ + {wrong # of entries in index i2} \ + {wrong # of entries in index i1} +] do_execsql_test e_reindex-1.4 { REINDEX; PRAGMA integrity_check; } {ok} Index: test/e_select.test ================================================================== --- test/e_select.test +++ test/e_select.test @@ -1016,20 +1016,20 @@ # EVIDENCE-OF: R-25883-55063 The expressions in the GROUP BY clause do # not have to be expressions that appear in the result. # do_select_tests e_select-4.9 { 1 "SELECT group_concat(one), two FROM b1 GROUP BY two" { - 4,5 f 1 o 6,7 s 2,3 t + 4,5 f 1 o 7,6 s 3,2 t } 2 "SELECT group_concat(one), sum(one) FROM b1 GROUP BY (one>4)" { - 1,2,3,4 10 5,6,7 18 + 1,4,3,2 10 5,7,6 18 } 3 "SELECT group_concat(one) FROM b1 GROUP BY (two>'o'), one%2" { 4 1,5 2,6 3,7 } 4 "SELECT group_concat(one) FROM b1 GROUP BY (one==2 OR two=='o')" { - 3,4,5,6,7 1,2 + 4,3,5,7,6 1,2 } } # EVIDENCE-OF: R-14926-50129 For the purposes of grouping rows, NULL # values are considered equal. @@ -1427,11 +1427,11 @@ } {} do_select_tests e_select-7.4 { 1 {SELECT a FROM q1 UNION ALL SELECT d FROM q2} {16 legible beauty legible beauty -65.91 emanating} - 2 {SELECT * FROM q1 WHERE a=16 UNION ALL SELECT 'x',* FROM q2 WHERE rowid=1} + 2 {SELECT * FROM q1 WHERE a=16 UNION ALL SELECT 'x', * FROM q2 WHERE oid=1} {16 -87.66 {} x legible 1} 3 {SELECT count(*) FROM q1 UNION ALL SELECT min(e) FROM q2} {3 -16.56} @@ -1445,11 +1445,11 @@ # do_select_tests e_select-7.5 { 1 {SELECT a FROM q1 UNION SELECT d FROM q2} {-65.91 16 beauty emanating legible} - 2 {SELECT * FROM q1 WHERE a=16 UNION SELECT 'x', * FROM q2 WHERE rowid=1} + 2 {SELECT * FROM q1 WHERE a=16 UNION SELECT 'x', * FROM q2 WHERE oid=1} {16 -87.66 {} x legible 1} 3 {SELECT count(*) FROM q1 UNION SELECT min(e) FROM q2} {-16.56 3} Index: test/e_update.test ================================================================== --- test/e_update.test +++ test/e_update.test @@ -202,13 +202,13 @@ # # EVIDENCE-OF: R-40472-60438 Columns that do not appear in the list of # assignments are left unmodified. # do_execsql_test e_update-1.5.0 { - INSERT INTO t2(a, b, c) VALUES(3, 1, 4); - INSERT INTO t2(a, b, c) VALUES(1, 5, 9); - INSERT INTO t2(a, b, c) VALUES(2, 6, 5); + INSERT INTO t2(rowid, a, b, c) VALUES(1, 3, 1, 4); + INSERT INTO t2(rowid, a, b, c) VALUES(2, 1, 5, 9); + INSERT INTO t2(rowid, a, b, c) VALUES(3, 2, 6, 5); } {} do_update_tests e_update-1.5 -query { SELECT * FROM t2 } { 1 "UPDATE t2 SET c = 1+1 WHERE a=2" @@ -251,13 +251,13 @@ # EVIDENCE-OF: R-04558-24451 In this case all scalar expressions are # evaluated before any assignments are made. # do_execsql_test e_update-1.7.0 { DELETE FROM t2; - INSERT INTO t2(a, b, c) VALUES(3, 1, 4); - INSERT INTO t2(a, b, c) VALUES(1, 5, 9); - INSERT INTO t2(a, b, c) VALUES(2, 6, 5); + INSERT INTO t2(rowid, a, b, c) VALUES(1, 3, 1, 4); + INSERT INTO t2(rowid, a, b, c) VALUES(2, 1, 5, 9); + INSERT INTO t2(rowid, a, b, c) VALUES(3, 2, 6, 5); } {} do_update_tests e_update-1.7 -query { SELECT * FROM t2 } { 1 "UPDATE t2 SET a=b+c" {5 1 4 14 5 9 11 6 5} @@ -274,49 +274,49 @@ INSERT INTO t3 VALUES(1, 'one'); INSERT INTO t3 VALUES(2, 'two'); INSERT INTO t3 VALUES(3, 'three'); INSERT INTO t3 VALUES(4, 'four'); } {} -foreach {tn sql error ts data } { +foreach {tn sql error ac data } { 1 "UPDATE t3 SET b='one' WHERE a=3" - {column b is not unique} 0 {1 one 2 two 3 three 4 four} + {column b is not unique} 1 {1 one 2 two 3 three 4 four} 2 "UPDATE OR REPLACE t3 SET b='one' WHERE a=3" - {} 0 {2 two 3 one 4 four} + {} 1 {2 two 3 one 4 four} 3 "UPDATE OR FAIL t3 SET b='three'" - {column b is not unique} 0 {2 three 3 one 4 four} + {column b is not unique} 1 {2 three 3 one 4 four} 4 "UPDATE OR IGNORE t3 SET b='three' WHERE a=3" - {} 0 {2 three 3 one 4 four} + {} 1 {2 three 3 one 4 four} 5 "UPDATE OR ABORT t3 SET b='three' WHERE a=3" - {column b is not unique} 0 {2 three 3 one 4 four} + {column b is not unique} 1 {2 three 3 one 4 four} - 6 "BEGIN" {} 1 {2 three 3 one 4 four} + 6 "BEGIN" {} 0 {2 three 3 one 4 four} 7 "UPDATE t3 SET b='three' WHERE a=3" - {column b is not unique} 1 {2 three 3 one 4 four} + {column b is not unique} 0 {2 three 3 one 4 four} 8 "UPDATE OR ABORT t3 SET b='three' WHERE a=3" - {column b is not unique} 1 {2 three 3 one 4 four} + {column b is not unique} 0 {2 three 3 one 4 four} 9 "UPDATE OR FAIL t3 SET b='two'" - {column b is not unique} 1 {2 two 3 one 4 four} + {column b is not unique} 0 {2 two 3 one 4 four} 10 "UPDATE OR IGNORE t3 SET b='four' WHERE a=3" - {} 1 {2 two 3 one 4 four} + {} 0 {2 two 3 one 4 four} 11 "UPDATE OR REPLACE t3 SET b='four' WHERE a=3" - {} 1 {2 two 3 four} + {} 0 {2 two 3 four} 12 "UPDATE OR ROLLBACK t3 SET b='four'" - {column b is not unique} 0 {2 three 3 one 4 four} + {column b is not unique} 1 {2 three 3 one 4 four} } { do_catchsql_test e_update-1.8.$tn.1 $sql [list [expr {$error!=""}] $error] do_execsql_test e_update-1.8.$tn.2 {SELECT * FROM t3} [list {*}$data] - do_test e_update-1.8.$tn.3 {sqlite4_db_transaction_status db} $ts + do_test e_update-1.8.$tn.3 {sqlite4_get_autocommit db} $ac } # EVIDENCE-OF: R-12123-54095 The table-name specified as part of an Index: test/enc2.test ================================================================== --- test/enc2.test +++ test/enc2.test @@ -87,11 +87,11 @@ INSERT INTO t1 VALUES('three','III',3); INSERT INTO t1 VALUES('four','IV',4); INSERT INTO t1 VALUES('five','V',5); } execsql {SELECT * FROM t1} -} {five V 5 four IV 4 one I 1 three III 3 two II 2} +} {one I 1 two II 2 three III 3 four IV 4 five V 5} # Use the index do_test $t.4 { execsql { SELECT * FROM t1 WHERE a = 'one'; @@ -113,20 +113,24 @@ # Now check that we can retrieve data in both UTF-16 and UTF-8 do_test $t.7 { set STMT [sqlite4_prepare $DB "SELECT a FROM t1 WHERE c>3;" -1 TAIL] sqlite4_step $STMT sqlite4_column_text $STMT 0 -} {five} +} {four} do_test $t.8 { sqlite4_step $STMT utf8 [sqlite4_column_text16 $STMT 0] -} {four} +} {five} do_test $t.9 { sqlite4_finalize $STMT } SQLITE4_OK + +ifcapable vacuum { + execsql VACUUM +} do_test $t.10 { db eval {PRAGMA encoding} } $enc Index: test/enc3.test ================================================================== --- test/enc3.test +++ test/enc3.test @@ -48,11 +48,11 @@ } {abcdef {}} do_test enc3-1.5 { execsql { SELECT quote(x) || ' ' || quote(y) FROM t1 } - } {{x'616263646566' NULL}} + } {{X'616263646566' NULL}} } ifcapable {bloblit && utf16} { do_test enc3-2.1 { execsql { PRAGMA encoding Index: test/errmsg.test ================================================================== --- test/errmsg.test +++ test/errmsg.test @@ -38,11 +38,11 @@ set ret } proc error_messages_v2 {sql {schema {}}} { - error_messages_worker sqlite4_prepare $sql $schema + error_messages_worker sqlite4_prepare_v2 $sql $schema } proc error_messages {sql {schema {}}} { error_messages_worker sqlite4_prepare $sql $schema } @@ -54,11 +54,11 @@ # Test error messages returned by user-defined SQL functions. # do_test 1.1 { error_messages "SELECT sql_error('custom message')" } [list {*}{ - SQLITE4_ERROR {custom message} + SQLITE4_ERROR {SQL logic error or missing database} SQLITE4_ERROR {custom message} }] do_test 1.2 { error_messages_v2 "SELECT sql_error('custom message')" } [list {*}{ @@ -75,11 +75,11 @@ INSERT INTO t1 VALUES('abc', 'def'); } do_test 2.2 { error_messages "INSERT INTO t1 VALUES('ghi', 'def')" } [list {*}{ - SQLITE4_CONSTRAINT {column b is not unique} + SQLITE4_ERROR {SQL logic error or missing database} SQLITE4_CONSTRAINT {column b is not unique} }] do_test 2.3 { error_messages_v2 "INSERT INTO t1 VALUES('ghi', 'def')" } [list {*}{ @@ -97,12 +97,12 @@ INSERT INTO t2 VALUES('abc', 'def'); } do_test 3.1.2 { error_messages "SELECT a FROM t2" "DROP TABLE t2" } [list {*}{ - SQLITE4_ERROR {no such table: t2} - SQLITE4_ERROR {no such table: t2} + SQLITE4_ERROR {SQL logic error or missing database} + SQLITE4_SCHEMA {database schema has changed} }] do_execsql_test 3.2.1 { CREATE TABLE t2(a PRIMARY KEY, b UNIQUE); INSERT INTO t2 VALUES('abc', 'def'); } Index: test/eval.test ================================================================== --- test/eval.test +++ test/eval.test @@ -50,11 +50,11 @@ execsql { CREATE TABLE t2(x,y); INSERT INTO t2 SELECT x, x+1 FROM t1 WHERE x<5; SELECT x, test_eval('DELETE FROM t2 WHERE x='||x), y FROM t2; } -} {1 {} 2 2 {} 3 3 {} 4 4 {} 5} +} {1 {} {} 2 {} {} 3 {} {} 4 {} {}} do_test eval-2.2 { execsql { SELECT * FROM t2 } } {} @@ -64,12 +64,12 @@ do_test eval-3.1 { execsql { INSERT INTO t2 SELECT x, x+1 FROM t1 WHERE x<5; SELECT x, test_eval('UPDATE t2 SET y=y+100 WHERE x='||x), y FROM t2; } -} {1 {} 2 2 {} 3 3 {} 4 4 {} 5} +} {1 {} 102 2 {} 103 3 {} 104 4 {} 105} do_test eval-4.1 { - execsql { SELECT test_eval('SELECT ''abcdefghij''') } + execsql { SELECT test_eval('SELECT "abcdefghij"') } } {abcdefghij} finish_test Index: test/expr.test ================================================================== --- test/expr.test +++ test/expr.test @@ -333,12 +333,12 @@ test_expr expr-2.21 {r1=2.34, r2=2.34} {r2==r1} 1 test_expr expr-2.22 {r1=1.23, r2=2.34} {min(r1,r2,r1+r2,r1-r2)} {-1.11} test_expr expr-2.23 {r1=1.23, r2=2.34} {max(r1,r2,r1+r2,r1-r2)} {3.57} test_expr expr-2.24 {r1=25.0, r2=11.0} {r1%r2} 3.0 test_expr expr-2.25 {r1=1.23, r2=NULL} {coalesce(r1+r2,99.0)} 99.0 - test_expr expr-2.26 {r1=1e600, r2=1e600} {coalesce((r1*r2)*0.0,99.0)} 99.0 - test_expr expr-2.26b {r1=1e300, r2=-1e300} {coalesce((r1*r2)*0.0,99.0)} 0.0 + test_expr expr-2.26 {r1=1e300, r2=1e300} {coalesce((r1*r2)*0.0,99.0)} 99.0 + test_expr expr-2.26b {r1=1e300, r2=-1e300} {coalesce((r1*r2)*0.0,99.0)} 99.0 test_expr expr-2.27 {r1=1.1, r2=0.0} {r1/r2} {{}} test_expr expr-2.28 {r1=1.1, r2=0.0} {r1%r2} {{}} } test_expr expr-3.1 {t1='abc', t2='xyz'} {t1 FROM
"), the following do # require a temp table. # do_test in3-1.6 { - exec_neph { SELECT rowid FROM t2 WHERE rowid IN (SELECT rowid+0 FROM t2); } + exec_neph { SELECT rowid FROM t1 WHERE rowid IN (SELECT rowid+0 FROM t1); } } {1 1 2 3} do_test in3-1.7 { exec_neph { SELECT a FROM t1 WHERE a IN (SELECT a+0 FROM t1); } } {1 1 3 5} do_test in3-1.8 { @@ -127,18 +122,27 @@ exec_neph { SELECT a FROM t1 WHERE a COLLATE nocase IN (SELECT a FROM t1) } } {1 1 3 5} do_test in3-1.15 { exec_neph { SELECT a FROM t1 WHERE a COLLATE binary IN (SELECT a FROM t1) } } {0 1 3 5} + +# Neither of these queries require a temp-table. The collation sequence +# makes no difference when using a rowid. +# +do_test in3-1.16 { + exec_neph {SELECT a FROM t1 WHERE a COLLATE nocase IN (SELECT rowid FROM t1)} +} {0 1 3} +do_test in3-1.17 { + exec_neph {SELECT a FROM t1 WHERE a COLLATE binary IN (SELECT rowid FROM t1)} +} {0 1 3} # The following tests - in3.2.* - test a bug that was difficult to track # down during development. They are not particularly well focused. # do_test in3-2.1 { execsql { DROP TABLE IF EXISTS t1; - DROP TABLE IF EXISTS t2; CREATE TABLE t1(w int, x int, y int); CREATE TABLE t2(p int, q int, r int, s int); } for {set i 1} {$i<=100} {incr i} { set w $i @@ -150,23 +154,23 @@ db eval { INSERT INTO t2 SELECT 101-w, x, $maxy+1-y, y FROM t1 } } {} do_test in3-2.2 { execsql { SELECT rowid - FROM t2 - WHERE rowid IN (SELECT rowid FROM t2 WHERE rowid IN (1, 2)); + FROM t1 + WHERE rowid IN (SELECT rowid FROM t1 WHERE rowid IN (1, 2)); } } {1 2} do_test in3-2.3 { execsql { - select rowid from t2 where rowid IN (-1,2,4) + select rowid from t1 where rowid IN (-1,2,4) } } {2 4} do_test in3-2.4 { execsql { - SELECT rowid FROM t2 WHERE rowid IN - (select rowid from t2 where rowid IN (-1,2,4)) + SELECT rowid FROM t1 WHERE rowid IN + (select rowid from t1 where rowid IN (-1,2,4)) } } {2 4} #------------------------------------------------------------------------- # This next block of tests - in3-3.* - verify that column affinity is @@ -254,12 +258,12 @@ do_test in3-4.4 { # A temp table must be used because t3_i.b is not guaranteed to be unique. exec_neph { SELECT b FROM t3 WHERE b IN (SELECT b FROM t3) } } {1 none numeric real text} do_test in3-4.5 { - execsql { CREATE UNIQUE INDEX t3_i2 ON t3(b) COVERING (b) } - exec_neph { SELECT b FROM t3 WHERE b IN (SELECT b FROM t3) ORDER BY b} + execsql { CREATE UNIQUE INDEX t3_i2 ON t3(b) } + exec_neph { SELECT b FROM t3 WHERE b IN (SELECT b FROM t3) } } {0 none numeric real text} do_test in3-4.6 { execsql { DROP INDEX t3_i2 } } {} Index: test/index.test ================================================================== --- test/index.test +++ test/index.test @@ -231,11 +231,11 @@ do_test index-7.3 { execsql { SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='test1' } -} {} +} {sqlite_autoindex_test1_1} do_test index-7.4 { execsql {DROP table test1} execsql {SELECT name FROM sqlite_master WHERE type!='meta'} } {} integrity_check index-7.5 @@ -351,12 +351,12 @@ } for {set i 1} {$i<=50} {incr i} { execsql "INSERT INTO t3 VALUES('x${i}x',$i,0.$i)" } set sqlite_search_count 0 - execsql {SELECT c FROM t3 WHERE b==10} -} {0.1} + concat [execsql {SELECT c FROM t3 WHERE b==10}] $sqlite_search_count +} {0.1 2} integrity_check index-11.2 # Numeric strings should compare as if they were numbers. So even if the # strings are not character-by-character the same, if they represent the @@ -426,14 +426,14 @@ SELECT * FROM t5; } } {1 2.0 3} do_test index-13.2 { set ::idxlist [execsql { - SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='t5'; + SELECT name FROM sqlite_master WHERE type="index" AND tbl_name="t5"; }] llength $::idxlist -} {2} +} {3} for {set i 0} {$i<[llength $::idxlist]} {incr i} { do_test index-13.3.$i { catchsql " DROP INDEX '[lindex $::idxlist $i]'; " @@ -569,11 +569,11 @@ execsql { DROP TABLE t7; CREATE TABLE t7(c PRIMARY KEY, UNIQUE(c) ); SELECT count(*) FROM sqlite_master WHERE tbl_name = 't7' AND type = 'index'; } -} {0} +} {1} do_test index-16.4 { execsql { DROP TABLE t7; CREATE TABLE t7(c, d , UNIQUE(c, d), PRIMARY KEY(c, d) ); SELECT count(*) FROM sqlite_master WHERE tbl_name = 't7' AND type = 'index'; @@ -583,11 +583,11 @@ execsql { DROP TABLE t7; CREATE TABLE t7(c, d , UNIQUE(c), PRIMARY KEY(c, d) ); SELECT count(*) FROM sqlite_master WHERE tbl_name = 't7' AND type = 'index'; } -} {1} +} {2} # Test that automatically create indices are named correctly. The current # convention is: "sqlite_autoindex_
_" # # Then check that it is an error to try to drop any automtically created @@ -596,19 +596,19 @@ execsql { DROP TABLE t7; CREATE TABLE t7(c, d UNIQUE, UNIQUE(c), PRIMARY KEY(c, d) ); SELECT name FROM sqlite_master WHERE tbl_name = 't7' AND type = 'index'; } -} {sqlite_t7_unique1 sqlite_t7_unique2} +} {sqlite_autoindex_t7_1 sqlite_autoindex_t7_2 sqlite_autoindex_t7_3} do_test index-17.2 { catchsql { - DROP INDEX sqlite_t7_unique1; + DROP INDEX sqlite_autoindex_t7_1; } } {1 {index associated with UNIQUE or PRIMARY KEY constraint cannot be dropped}} do_test index-17.3 { catchsql { - DROP INDEX IF EXISTS sqlite_t7_unique1; + DROP INDEX IF EXISTS sqlite_autoindex_t7_1; } } {1 {index associated with UNIQUE or PRIMARY KEY constraint cannot be dropped}} do_test index-17.4 { catchsql { DROP INDEX IF EXISTS no_such_index; @@ -664,21 +664,21 @@ do_test index-19.2 { catchsql { BEGIN; INSERT INTO t7 VALUES(1); } - } {1 {PRIMARY KEY must be unique}} + } {1 {column a is not unique}} do_test index-19.3 { catchsql { BEGIN; } } {1 {cannot start a transaction within a transaction}} do_test index-19.4 { catchsql { INSERT INTO t8 VALUES(1); } - } {1 {PRIMARY KEY must be unique}} + } {1 {column a is not unique}} do_test index-19.5 { catchsql { BEGIN; COMMIT; } Index: test/interrupt.test ================================================================== --- test/interrupt.test +++ test/interrupt.test @@ -78,15 +78,23 @@ SELECT count(*) from t1; } } 64 set origsize [file size test.db] set cksum [db eval {SELECT md5sum(a || b) FROM t1}] +ifcapable {vacuum} { + interrupt_test interrupt-2.2 {VACUUM} {} 100 +} do_test interrupt-2.3 { execsql { SELECT md5sum(a || b) FROM t1; } } $cksum +ifcapable {vacuum && !default_autovacuum} { + do_test interrupt-2.4 { + expr {$::origsize>[file size test.db]} + } 1 +} ifcapable {explain} { do_test interrupt-2.5 { set sql {EXPLAIN SELECT max(a,b), a, b FROM t1} execsql $sql set rc [catch {db eval $sql {sqlite4_interrupt $DB}} msg] DELETED test/kvstore.test Index: test/kvstore.test ================================================================== --- test/kvstore.test +++ /dev/null @@ -1,121 +0,0 @@ -# 2013 Jul 31 -# -# 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. -# -#*********************************************************************** -# This file implements regression tests for SQLite library. The -# focus of this file is testing the SELECT statement. -# - -set testdir [file dirname $argv0] -source $testdir/tester.tcl - -set ::testprefix kvstore - - -do_execsql_test 1.1 { - SELECT * FROM sqlite_kvstore ; - CREATE TABLE t1(x); -} {} - -do_execsql_test 1.2 { - SELECT quote(key), quote(value) FROM sqlite_kvstore ; -} [list \ - x'011802' \ - x'052a1e1e035e7461626c657431743102435245415445205441424c45207431287829' -] - -do_execsql_test 1.3 { - SELECT quote(key), quote(value) FROM sqlite_temp_kvstore ; -} {} - - -do_execsql_test 2.1 { - CREATE TABLE t2(x PRIMARY KEY, y UNIQUE); - INSERT INTO t2 VALUES(1, 2); - INSERT INTO t2 VALUES(3, 4); - CREATE INDEX i1 ON t2(y DESC, x DESC); -} -array unset ::data -db eval { SELECT quote(key) AS k, quote(value) AS v FROM sqlite_kvstore } { - set ::data($k) $v -} -do_execsql_test 2.2 { - SELECT quote(key) FROM sqlite_kvstore ORDER BY key DESC; -} [lsort -decreasing [array names ::data]] -do_execsql_test 2.3 { - SELECT quote(key) FROM sqlite_kvstore ORDER BY key ASC; -} [lsort -incr [array names ::data]] - -set i 0 -foreach k [array names ::data] { - do_execsql_test 2.4.$i " - SELECT quote(value) FROM sqlite_kvstore WHERE key = $k - " $::data($k) - incr i -} - -proc key_range {a b} { - set res [list] - foreach k [lsort [array names ::data]] { - if {[string compare $k $a]>=0 && [string compare $k $b]<=0} { - lappend res $k - } - } - set res -} - -set sorted_keys [lsort [array names ::data]] -set nKey [llength $sorted_keys] -for {set i 0} {$i < $nKey} {incr i} { - for {set i2 $i} {$i2 < $nKey} {incr i2} { - set k1 [lindex $sorted_keys $i] - set k2 [lindex $sorted_keys $i2] - - set sql "SELECT quote(key) FROM sqlite_kvstore WHERE key>=$k1 AND key<=$k2" - set s1 [lsort [key_range $k1 $k2]] - set s2 [lsort -decr [key_range $k1 $k2]] - - do_execsql_test 2.4.1.$i.$i2.asc " $sql ORDER BY key ASC " $s1 - do_execsql_test 2.4.1.$i.$i2.desc " $sql ORDER BY key DESC " $s2 - - set sql "SELECT quote(key) FROM sqlite_kvstore WHERE key>$k1 AND key<=$k2" - set s1 [lrange [lsort [key_range $k1 $k2]] 1 end] - set s2 [lsort -decr $s1] - - do_execsql_test 2.4.2.$i.$i2.asc " $sql ORDER BY key ASC " $s1 - do_execsql_test 2.4.2.$i.$i2.desc " $sql ORDER BY key DESC " $s2 - - set sql "SELECT quote(key) FROM sqlite_kvstore WHERE key>=$k1 AND key<$k2" - set s1 [lrange [lsort [key_range $k1 $k2]] 0 end-1] - set s2 [lsort -decr $s1] - - do_execsql_test 2.4.3.$i.$i2.asc " $sql ORDER BY key ASC " $s1 - do_execsql_test 2.4.3.$i.$i2.desc " $sql ORDER BY key DESC " $s2 - - set sql "SELECT quote(key) FROM sqlite_kvstore WHERE key>$k1 AND key<$k2" - set s1 [lrange [lsort [key_range $k1 $k2]] 1 end-1] - set s2 [lsort -decr $s1] - - do_execsql_test 2.4.4.$i.$i2.asc " $sql ORDER BY key ASC " $s1 - do_execsql_test 2.4.4.$i.$i2.desc " $sql ORDER BY key DESC " $s2 - do_execsql_test 2.4.4.$i.$i2.asc " $sql ORDER BY key ASC " $s1 - do_execsql_test 2.4.4.$i.$i2.desc " $sql ORDER BY key DESC " $s2 - - } -} - - - - - - - - -finish_test - Index: test/laststmtchanges.test ================================================================== --- test/laststmtchanges.test +++ test/laststmtchanges.test @@ -148,11 +148,11 @@ catchsql { drop trigger r1; delete from t2; delete from t2; create trigger r1 after update on t1 for each row begin insert into t2 values (NULL, changes(), NULL); - delete from t0 where rowid=1 or rowid=2; + delete from t0 where oid=1 or oid=2; update t2 set v2=changes(); end; update t1 set k=k; select changes(); } Index: test/like.test ================================================================== --- test/like.test +++ test/like.test @@ -129,24 +129,24 @@ } } {abc abcd} # Tests of the MATCH operator # -# do_test like-2.3 { -# proc test_match {a b} { -# return [string match $a $b] -# } -# db function match -argcount 2 test_match -# execsql { -# SELECT x FROM t1 WHERE x MATCH '*abc*' ORDER BY 1; -# } -# } {{ABC abc xyz} abc abcd} -# do_test like-2.4 { -# execsql { -# SELECT x FROM t1 WHERE x MATCH 'abc*' ORDER BY 1; -# } -# } {abc abcd} +do_test like-2.3 { + proc test_match {a b} { + return [string match $a $b] + } + db function match -argcount 2 test_match + execsql { + SELECT x FROM t1 WHERE x MATCH '*abc*' ORDER BY 1; + } +} {{ABC abc xyz} abc abcd} +do_test like-2.4 { + execsql { + SELECT x FROM t1 WHERE x MATCH 'abc*' ORDER BY 1; + } +} {abc abcd} # For the remaining tests, we need to have the like optimizations # enabled. # ifcapable !like_opt { @@ -154,31 +154,18 @@ return } # This procedure executes the SQL. Then it appends to the result the # "sort" or "nosort" keyword (as in the cksort procedure above) then -# it appends the names of the table and index used. +# it appends the ::sqlite_query_plan variable. # proc queryplan {sql} { set ::sqlite_sort_count 0 set data [execsql $sql] if {$::sqlite_sort_count} {set x sort} {set x nosort} lappend data $x - set eqp [execsql "EXPLAIN QUERY PLAN $sql"] - # puts eqp=$eqp - foreach {a b c x} $eqp { - if {[regexp { TABLE (\w+ AS )?(\w+) USING COVERING INDEX (\w+)\y} \ - $x all as tab idx]} { - lappend data {} $idx - } elseif {[regexp { TABLE (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \ - $x all as tab idx]} { - lappend data $tab $idx - } elseif {[regexp { TABLE (\w+ AS )?(\w+)\y} $x all as tab]} { - lappend data $tab * - } - } - return $data + return [concat $data $::sqlite_query_plan] } # Perform tests on the like optimization. # # With no index on t1.x and with case sensitivity turned off, no optimization @@ -187,11 +174,11 @@ do_test like-3.1 { set sqlite_like_count 0 queryplan { SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1; } -} {ABC {ABC abc xyz} abc abcd sort t1 *} +} {ABC {ABC abc xyz} abc abcd sort t1 {}} do_test like-3.2 { set sqlite_like_count } {12} # With an index on t1.x and case sensitivity on, optimize completely. @@ -203,11 +190,11 @@ CREATE INDEX i1 ON t1(x); } queryplan { SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1; } -} {abc abcd nosort t1 i1} +} {abc abcd nosort {} i1} do_test like-3.4 { set sqlite_like_count } 0 # The LIKE optimization still works when the RHS is a string with no @@ -215,54 +202,54 @@ # do_test like-3.4.2 { queryplan { SELECT x FROM t1 WHERE x LIKE 'a' ORDER BY 1; } -} {a nosort t1 i1} +} {a nosort {} i1} do_test like-3.4.3 { queryplan { SELECT x FROM t1 WHERE x LIKE 'ab' ORDER BY 1; } -} {ab nosort t1 i1} +} {ab nosort {} i1} do_test like-3.4.4 { queryplan { SELECT x FROM t1 WHERE x LIKE 'abcd' ORDER BY 1; } -} {abcd nosort t1 i1} +} {abcd nosort {} i1} do_test like-3.4.5 { queryplan { SELECT x FROM t1 WHERE x LIKE 'abcde' ORDER BY 1; } -} {nosort t1 i1} +} {nosort {} i1} # Partial optimization when the pattern does not end in '%' # do_test like-3.5 { set sqlite_like_count 0 queryplan { SELECT x FROM t1 WHERE x LIKE 'a_c' ORDER BY 1; } -} {abc nosort t1 i1} +} {abc nosort {} i1} do_test like-3.6 { set sqlite_like_count } 6 do_test like-3.7 { set sqlite_like_count 0 queryplan { SELECT x FROM t1 WHERE x LIKE 'ab%d' ORDER BY 1; } -} {abcd abd nosort t1 i1} +} {abcd abd nosort {} i1} do_test like-3.8 { set sqlite_like_count } 4 do_test like-3.9 { set sqlite_like_count 0 queryplan { SELECT x FROM t1 WHERE x LIKE 'a_c%' ORDER BY 1; } -} {abc abcd nosort t1 i1} +} {abc abcd nosort {} i1} do_test like-3.10 { set sqlite_like_count } 6 # No optimization when the pattern begins with a wildcard. @@ -271,40 +258,38 @@ do_test like-3.11 { set sqlite_like_count 0 queryplan { SELECT x FROM t1 WHERE x LIKE '%bcd' ORDER BY 1; } -} {abcd bcd nosort t1 i1} +} {abcd bcd nosort {} i1} do_test like-3.12 { set sqlite_like_count } 12 # No optimization for case insensitive LIKE # do_test like-3.13 { set sqlite_like_count 0 - db eval {PRAGMA case_sensitive_like=off;} queryplan { + PRAGMA case_sensitive_like=off; SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1; } -} {ABC {ABC abc xyz} abc abcd nosort t1 i1} +} {ABC {ABC abc xyz} abc abcd nosort {} i1} do_test like-3.14 { set sqlite_like_count } 12 # No optimization without an index. # do_test like-3.15 { set sqlite_like_count 0 - db eval { + queryplan { PRAGMA case_sensitive_like=on; DROP INDEX i1; - } - queryplan { SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1; } -} {abc abcd sort t1 *} +} {abc abcd sort t1 {}} do_test like-3.16 { set sqlite_like_count } 12 # No GLOB optimization without an index. @@ -312,11 +297,11 @@ do_test like-3.17 { set sqlite_like_count 0 queryplan { SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1; } -} {abc abcd sort t1 *} +} {abc abcd sort t1 {}} do_test like-3.18 { set sqlite_like_count } 12 # GLOB is optimized regardless of the case_sensitive_like setting. @@ -325,31 +310,31 @@ set sqlite_like_count 0 db eval {CREATE INDEX i1 ON t1(x);} queryplan { SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1; } -} {abc abcd nosort t1 i1} +} {abc abcd nosort {} i1} do_test like-3.20 { set sqlite_like_count } 0 do_test like-3.21 { set sqlite_like_count 0 - db eval {PRAGMA case_sensitive_like=on;} queryplan { + PRAGMA case_sensitive_like=on; SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1; } -} {abc abcd nosort t1 i1} +} {abc abcd nosort {} i1} do_test like-3.22 { set sqlite_like_count } 0 do_test like-3.23 { set sqlite_like_count 0 - db eval {PRAGMA case_sensitive_like=off;} queryplan { + PRAGMA case_sensitive_like=off; SELECT x FROM t1 WHERE x GLOB 'a[bc]d' ORDER BY 1; } -} {abd acd nosort t1 i1} +} {abd acd nosort {} i1} do_test like-3.24 { set sqlite_like_count } 6 # GLOB optimization when there is no wildcard. Ticket [e090183531fc2747] @@ -356,21 +341,21 @@ # do_test like-3.25 { queryplan { SELECT x FROM t1 WHERE x GLOB 'a' ORDER BY 1; } -} {a nosort t1 i1} +} {a nosort {} i1} do_test like-3.26 { queryplan { SELECT x FROM t1 WHERE x GLOB 'abcd' ORDER BY 1; } -} {abcd nosort t1 i1} +} {abcd nosort {} i1} do_test like-3.27 { queryplan { SELECT x FROM t1 WHERE x GLOB 'abcde' ORDER BY 1; } -} {nosort t1 i1} +} {nosort {} i1} # No optimization if the LHS of the LIKE is not a column name or # if the RHS is not a string. @@ -379,29 +364,29 @@ execsql {PRAGMA case_sensitive_like=on} set sqlite_like_count 0 queryplan { SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1 } -} {abc abcd nosort t1 i1} +} {abc abcd nosort {} i1} do_test like-4.2 { set sqlite_like_count } 0 do_test like-4.3 { set sqlite_like_count 0 queryplan { SELECT x FROM t1 WHERE +x LIKE 'abc%' ORDER BY 1 } -} {abc abcd nosort t1 i1} +} {abc abcd nosort {} i1} do_test like-4.4 { set sqlite_like_count } 12 do_test like-4.5 { set sqlite_like_count 0 queryplan { SELECT x FROM t1 WHERE x LIKE ('ab' || 'c%') ORDER BY 1 } -} {abc abcd nosort t1 i1} +} {abc abcd nosort {} i1} do_test like-4.6 { set sqlite_like_count } 12 # Collating sequences on the index disable the LIKE optimization. @@ -412,25 +397,25 @@ execsql {PRAGMA case_sensitive_like=off} set sqlite_like_count 0 queryplan { SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1 } -} {ABC {ABC abc xyz} abc abcd nosort t1 i1} +} {ABC {ABC abc xyz} abc abcd nosort {} i1} do_test like-5.2 { set sqlite_like_count } 12 do_test like-5.3 { execsql { CREATE TABLE t2(x TEXT COLLATE NOCASE); - INSERT INTO t2 SELECT * FROM t1 ORDER BY rowid; + INSERT INTO t2 SELECT * FROM t1; CREATE INDEX i2 ON t2(x COLLATE NOCASE); } set sqlite_like_count 0 queryplan { SELECT x FROM t2 WHERE x LIKE 'abc%' ORDER BY 1 } -} {abc ABC {ABC abc xyz} abcd nosort t2 i2} +} {abc ABC {ABC abc xyz} abcd nosort {} i2} do_test like-5.4 { set sqlite_like_count } 0 do_test like-5.5 { execsql { @@ -438,11 +423,11 @@ } set sqlite_like_count 0 queryplan { SELECT x FROM t2 WHERE x LIKE 'abc%' ORDER BY 1 } -} {abc abcd nosort t2 i2} +} {abc abcd nosort {} i2} do_test like-5.6 { set sqlite_like_count } 12 do_test like-5.7 { execsql { @@ -450,30 +435,30 @@ } set sqlite_like_count 0 queryplan { SELECT x FROM t2 WHERE x GLOB 'abc*' ORDER BY 1 } -} {abc abcd nosort t2 i2} +} {abc abcd nosort {} i2} do_test like-5.8 { set sqlite_like_count } 12 do_test like-5.11 { execsql {PRAGMA case_sensitive_like=off} set sqlite_like_count 0 queryplan { SELECT x FROM t1 WHERE x LIKE 'ABC%' ORDER BY 1 } -} {ABC {ABC abc xyz} abc abcd nosort t1 i1} +} {ABC {ABC abc xyz} abc abcd nosort {} i1} do_test like-5.12 { set sqlite_like_count } 12 do_test like-5.13 { set sqlite_like_count 0 queryplan { SELECT x FROM t2 WHERE x LIKE 'ABC%' ORDER BY 1 } -} {abc ABC {ABC abc xyz} abcd nosort t2 i2} +} {abc ABC {ABC abc xyz} abcd nosort {} i2} do_test like-5.14 { set sqlite_like_count } 0 do_test like-5.15 { execsql { @@ -481,11 +466,11 @@ } set sqlite_like_count 0 queryplan { SELECT x FROM t2 WHERE x LIKE 'ABC%' ORDER BY 1 } -} {ABC {ABC abc xyz} nosort t2 i2} +} {ABC {ABC abc xyz} nosort {} i2} do_test like-5.16 { set sqlite_like_count } 12 do_test like-5.17 { execsql { @@ -493,11 +478,11 @@ } set sqlite_like_count 0 queryplan { SELECT x FROM t2 WHERE x GLOB 'ABC*' ORDER BY 1 } -} {ABC {ABC abc xyz} nosort t2 i2} +} {ABC {ABC abc xyz} nosort {} i2} do_test like-5.18 { set sqlite_like_count } 12 # Boundary case. The prefix for a LIKE comparison is rounded up @@ -518,26 +503,26 @@ INSERT INTO t2 VALUES('zz-lower-lower'); } queryplan { SELECT x FROM t2 WHERE x LIKE 'zz%'; } -} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort t2 i2} +} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2} do_test like-5.22 { queryplan { SELECT x FROM t2 WHERE x LIKE 'zZ%'; } -} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort t2 i2} +} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2} do_test like-5.23 { queryplan { SELECT x FROM t2 WHERE x LIKE 'Zz%'; } -} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort t2 i2} +} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2} do_test like-5.24 { queryplan { SELECT x FROM t2 WHERE x LIKE 'ZZ%'; } -} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort t2 i2} +} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2} do_test like-5.25 { db eval { PRAGMA case_sensitive_like=on; CREATE TABLE t3(x TEXT); CREATE INDEX i3 ON t3(x); @@ -547,26 +532,26 @@ INSERT INTO t3 VALUES('zz-lower-lower'); } queryplan { SELECT x FROM t3 WHERE x LIKE 'zz%'; } -} {zz-lower-lower nosort t3 i3} +} {zz-lower-lower nosort {} i3} do_test like-5.26 { queryplan { SELECT x FROM t3 WHERE x LIKE 'zZ%'; } -} {zZ-lower-upper nosort t3 i3} +} {zZ-lower-upper nosort {} i3} do_test like-5.27 { queryplan { SELECT x FROM t3 WHERE x LIKE 'Zz%'; } -} {Zz-upper-lower nosort t3 i3} +} {Zz-upper-lower nosort {} i3} do_test like-5.28 { queryplan { SELECT x FROM t3 WHERE x LIKE 'ZZ%'; } -} {ZZ-upper-upper nosort t3 i3} +} {ZZ-upper-upper nosort {} i3} # ticket #2407 # # Make sure the LIKE prefix optimization does not strip off leading @@ -675,12 +660,12 @@ ifcapable explain { do_test like-9.4.3 { set res [sqlite4_exec_hex db { EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%ff%25' }] - regexp {SCAN TABLE t2} $res - } {1} + regexp {INDEX i2} $res + } {0} } do_test like-9.5.1 { set res [sqlite4_exec_hex db { SELECT x FROM t2 WHERE x LIKE '%fe%25' }] @@ -747,11 +732,11 @@ } {12 123 scan 5 like 6} do_test like-10.5 { count { SELECT a FROM t10 WHERE f LIKE '12%' ORDER BY +a; } - } {12 123 scan 2 like 0} + } {12 123 scan 3 like 0} do_test like-10.6 { count { SELECT a FROM t10 WHERE a LIKE '12%' ORDER BY +a; } } {12 123 scan 5 like 6} @@ -788,11 +773,11 @@ } {12 123 scan 5 like 6} do_test like-10.14 { count { SELECT a FROM t10b WHERE f GLOB '12*' ORDER BY +a; } - } {12 123 scan 2 like 0} + } {12 123 scan 3 like 0} do_test like-10.15 { count { SELECT a FROM t10b WHERE a GLOB '12*' ORDER BY +a; } } {12 123 scan 5 like 6} @@ -822,76 +807,70 @@ INSERT INTO t11 VALUES(12, 'YZ','YZ'); SELECT count(*) FROM t11; } } {12} do_test like-11.1 { - db eval {PRAGMA case_sensitive_like=OFF;} queryplan { + PRAGMA case_sensitive_like=OFF; SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a; } } {abc abcd ABC ABCD nosort t11 *} do_test like-11.2 { - db eval {PRAGMA case_sensitive_like=ON;} queryplan { + PRAGMA case_sensitive_like=ON; SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a; } } {abc abcd nosort t11 *} do_test like-11.3 { - db eval { + queryplan { PRAGMA case_sensitive_like=OFF; CREATE INDEX t11b ON t11(b); - } - queryplan { SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a; } -} {abc abcd ABC ABCD sort t11 t11b} +} {abc abcd ABC ABCD sort {} t11b} do_test like-11.4 { - db eval {PRAGMA case_sensitive_like=ON;} queryplan { + PRAGMA case_sensitive_like=ON; SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a; } } {abc abcd nosort t11 *} do_test like-11.5 { - db eval { + queryplan { PRAGMA case_sensitive_like=OFF; DROP INDEX t11b; CREATE INDEX t11bnc ON t11(b COLLATE nocase); - } - queryplan { - SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a; - } -} {abc abcd ABC ABCD sort t11 t11bnc} -do_test like-11.6 { - db eval {CREATE INDEX t11bb ON t11(b COLLATE binary);} - queryplan { - SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a; - } -} {abc abcd ABC ABCD sort t11 t11bnc} -do_test like-11.7 { - db eval {PRAGMA case_sensitive_like=ON;} - queryplan { - SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a; - } -} {abc abcd sort t11 t11bb} -do_test like-11.8 { - db eval {PRAGMA case_sensitive_like=OFF;} - queryplan { - SELECT b FROM t11 WHERE b GLOB 'abc*' ORDER BY +a; - } -} {abc abcd sort t11 t11bb} -do_test like-11.9 { - db eval { - CREATE INDEX t11cnc ON t11(c COLLATE nocase); - CREATE INDEX t11cb ON t11(c COLLATE binary); - } - queryplan { - SELECT c FROM t11 WHERE c LIKE 'abc%' ORDER BY +a; - } -} {abc abcd ABC ABCD sort t11 t11cnc} + SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a; + } +} {abc abcd ABC ABCD sort {} t11bnc} +do_test like-11.6 { + queryplan { + CREATE INDEX t11bb ON t11(b COLLATE binary); + SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a; + } +} {abc abcd ABC ABCD sort {} t11bnc} +do_test like-11.7 { + queryplan { + PRAGMA case_sensitive_like=ON; + SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a; + } +} {abc abcd sort {} t11bb} +do_test like-11.8 { + queryplan { + PRAGMA case_sensitive_like=OFF; + SELECT b FROM t11 WHERE b GLOB 'abc*' ORDER BY +a; + } +} {abc abcd sort {} t11bb} +do_test like-11.9 { + queryplan { + CREATE INDEX t11cnc ON t11(c COLLATE nocase); + CREATE INDEX t11cb ON t11(c COLLATE binary); + SELECT c FROM t11 WHERE c LIKE 'abc%' ORDER BY +a; + } +} {abc abcd ABC ABCD sort {} t11cnc} do_test like-11.10 { queryplan { SELECT c FROM t11 WHERE c GLOB 'abc*' ORDER BY +a; } -} {abc abcd sort t11 t11cb} +} {abc abcd sort {} t11cb} finish_test Index: test/lsm5.test ================================================================== --- test/lsm5.test +++ test/lsm5.test @@ -55,11 +55,11 @@ db write 1 one db write 2 two db close } {} do_test 1.3 { - expr [file size test.db] <= (256*1024) + expr [file size test.db] < (64*1024) } 1 #------------------------------------------------------------------------- # Test that if an attempt is made to open a read-write connection to a # non-live database that the client does not have permission to write to is Index: test/num.test ================================================================== --- test/num.test +++ test/num.test @@ -58,49 +58,23 @@ do_test num-3.1.1 { sqlite4_num_to_text [sqlite4_num_add 5 7] } {12} -foreach {tn a b difference} { - 1 9 3 6 - 2 5 12 -7 - 3 -9 -10 1 - 4 -2 4 -6 - 5 -48 -48 0 - 6 NaN 4 NaN - 7 95 NaN NaN - 8 NaN inf NaN - 9 inf inf NaN - 10 -inf -inf NaN - 11 inf -inf inf - 12 -inf 955 -inf - 13 -inf inf -inf -} { - do_test num-4.1.$tn { - sqlite4_num_to_text [sqlite4_num_sub $a $b] - } $difference -} +do_test num-4.1.1 { + sqlite4_num_to_text [sqlite4_num_sub 9 3] +} {6} +do_test num-4.1.2 { + sqlite4_num_to_text [sqlite4_num_sub 5 12] +} {-7} do_test num-4.2.1 { sqlite4_num_compare [sqlite4_num_sub 1 1] [sqlite4_num_sub -1 -1] } {equal} - -foreach {tn a b product} { - 1 9 8 72 - 2 NaN inf NaN - 3 inf NaN NaN - 4 inf 0 NaN - 5 inf -inf -inf - 6 NaN 0 NaN - 7 NaN 1 NaN - 8 NaN -9 NaN - 9 NaN NaN NaN -} { - do_test num-5.1.$tn { - sqlite4_num_to_text [sqlite4_num_mul $a $b] - } $product -} +do_test num-5.1.1 { + sqlite4_num_to_text [sqlite4_num_mul 9 8] +} {72} do_test num-6.1.1 { sqlite4_num_to_text [sqlite4_num_div 6 5] } {1.2} do_test num-6.1.2 { Index: test/permutations.test ================================================================== --- test/permutations.test +++ test/permutations.test @@ -136,64 +136,50 @@ simple.test simple2.test lsm1.test lsm2.test lsm3.test lsm4.test lsm5.test csr1.test ckpt1.test mc1.test - fts5expr1.test fts5query1.test fts5rnd1.test fts5create.test fts5snippet.test + fts5expr1.test fts5query1.test fts5rnd1.test fts5create.test + fts5snippet.test - alter.test alter3.test alter4.test analyze.test analyze3.test analyze4.test analyze5.test - analyze6.test analyze7.test analyze8.test + analyze6.test analyze7.test auth.test auth2.test auth3.test auth4.test aggerror.test - attach.test attach3.test attach4.test + attach.test autoindex1.test - badutf.test badutf2.test + badutf.test between.test bigrow.test bind.test - blob.test - boundary1.test boundary2.test boundary3.test boundary4.test - capi2.test + + boundary1.test boundary4.test cast.test - check.test coalesce.test collate1.test collate2.test collate3.test collate4.test collate5.test collate6.test collate7.test collate8.test collate9.test collateA.test - collateerr.test - covidx.test conflict.test count.test - createtab.test cse.test ctime.test date.test - default.test - delete.test delete2.test delete3.test - descidx1.test descidx2.test descidx3.test + delete.test delete2.test distinct.test distinctagg.test - e_createtable.test e_delete.test e_droptrigger.test e_dropview.test - e_expr.test e_fkey.test e_insert.test e_reindex.test - e_resolve.test e_select.test e_select2.test e_update.test - enc.test enc3.test enc4.test - errmsg.test - eval.test - expr.test - exec.test + enc.test enc4.test exists.test + e_droptrigger.test e_dropview.test + e_resolve.test e_dropview.test + e_select2.test fkey1.test fkey2.test fkey3.test fkey4.test func.test func2.test func3.test - fuzz.test fuzz2.test - in.test in2.test in3.test in4.test - index.test index2.test index3.test index4.test + fuzz2.test + in.test in4.test + index2.test index3.test index4.test insert.test insert2.test insert3.test insert5.test join.test join2.test join3.test join4.test join5.test join6.test keyword1.test - kvstore.test - laststmtchanges.test limit.test - like.test like2.test main.test manydb.test misc5.test misc6.test misuse.test notnull.test Index: test/simple.test ================================================================== --- test/simple.test +++ test/simple.test @@ -695,16 +695,11 @@ CREATE TRIGGER tr1 INSTEAD OF DELETE ON v1 BEGIN INSERT INTO log VALUES(old.b, old.a); END; } do_execsql_test 38.3 { - SELECT * FROM v1; -} {3 4} -do_execsql_test 38.4 { DELETE FROM v1 WHERE a = 3; -} -do_execsql_test 38.5 { SELECT * FROM log; } {4 3} #------------------------------------------------------------------------- reset_db @@ -1364,15 +1359,15 @@ do_catchsql_test 70.2 { select * from maintable as m inner join joinme as j indexed by joinme_id_text_idx on ( m.id = j.id_int) -} {1 {no query solution}} +} {1 {cannot use index: joinme_id_text_idx}} do_catchsql_test 70.3 { select * from maintable, joinme INDEXED by joinme_id_text_idx -} {1 {no query solution}} +} {1 {cannot use index: joinme_id_text_idx}} #------------------------------------------------------------------------- # This is testing that the "phantom" runs feature works. # # UPDATE: Said feature was dropped early in development. But the test @@ -1562,168 +1557,8 @@ } do_execsql_test 80.2 { SELECT idx, count(*), sum(length(sample)) FROM t1 GROUP BY idx } {t1 2 4 t1i1 2 4 t1i2 2 4 t1i3 2 4} - -#------------------------------------------------------------------------- -reset_db -do_test 81.1 { - execsql { - CREATE TABLE t1(a TEXT); - INSERT INTO t1 VALUES(5.4e-08); - SELECT a FROM t1; - } -} {5.4e-8} - -#------------------------------------------------------------------------- -reset_db -do_test 82.1 { - execsql { CREATE TABLE t1(a TEXT) } - execsql { SELECT * FROM sqlite_master } -} {table t1 t1 2 {CREATE TABLE t1(a TEXT)}} - -do_test 82.2 { - execsql { DROP TABLE t1 } - execsql { CREATE TABLE t1(a TEXT) } - execsql { SELECT * FROM sqlite_master } -} {table t1 t1 2 {CREATE TABLE t1(a TEXT)}} - -#------------------------------------------------------------------------- -reset_db -do_test 83.1 { - execsql { SELECT CAST('2.12e-01ABC' AS INT) } -} {2} -do_test 83.2 { - execsql { SELECT CAST(' -2.12e-01ABC' AS INT) } -} {-2} -do_test 83.3 { - execsql { SELECT CAST('45.0' AS NUMERIC) } -} {45} -do_test 83.4 { - execsql { SELECT CAST(0.0 AS TEXT) } -} {0.0} - -#------------------------------------------------------------------------- -reset_db -do_execsql_test 84.1 { - SELECT 1e600 * 1e600 * 0.0; -} {{}} - -#------------------------------------------------------------------------- -reset_db -do_execsql_test 85.1 { - CREATE TABLE t1(x INT, y COLLATE NOCASE); - INSERT INTO t1(x,y) VALUES(2,CAST(x'02' AS TEXT)); - CREATE TABLE t3(x INT, y COLLATE NOCASE); - INSERT INTO t3 SELECT x, 'abc' || y || 'xyz' FROM t1; - CREATE INDEX i3 ON t3(y); - SELECT x FROM t3 WHERE y LIKE 'abcX%'; -} {} - -#------------------------------------------------------------------------- -reset_db -do_execsql_test 86.0 { - SELECT * FROM sqlite_master; -} {} -do_execsql_test 86.1 { - CREATE TABLE t1(a PRIMARY KEY, b); -} -do_execsql_test 86.2 { - INSERT INTO t1 VALUES(1, 'one'); -} -do_execsql_test 86.3 { - SELECT * FROM t1; -} {1 one} -do_execsql_test 86.4 { - SELECT * FROM t1 WHERE a = 1; -} {1 one} - -#------------------------------------------------------------------------- -reset_db -do_execsql_test 87.1 { - CREATE TABLE t6(a INTEGER PRIMARY KEY, b TEXT); - CREATE INDEX t6i1 ON t6(b); -} {} -do_eqp_test 87.2 { - SELECT * FROM t6 ORDER BY b, a; -} {0 0 0 {SCAN TABLE t6 USING INDEX t6i1}} - -#------------------------------------------------------------------------- -reset_db -do_execsql_test 88.1 { - CREATE TABLE t8(a INTEGER PRIMARY KEY, b TEXT); - CREATE UNIQUE INDEX t8i ON t8(b); -} -do_eqp_test 88.2 { - SELECT * FROM t8 x ORDER BY x.b, x.a, x.b||x.a -} {0 0 0 {SCAN TABLE t8 AS x USING INDEX t8i}} - -#------------------------------------------------------------------------- -reset_db -do_execsql_test 89.1 { - CREATE TABLE t1(a COLLATE NOCASE); - CREATE INDEX i1 ON t1(a); -} -do_eqp_test 89.2 { - SELECT * FROM t1 ORDER BY a; -} {0 0 0 {SCAN TABLE t1 USING INDEX i1}} - -#------------------------------------------------------------------------- - -proc nEphemeral {sql} { - set nEph 0 - foreach op [execsql "EXPLAIN $sql"] { - if {$op eq "OpenEphemeral"} {incr nEph} - } - set nEph -} - -foreach {tn schema} { - 1 { - CREATE TABLE t1(a PRIMARY KEY, b); - CREATE TABLE t2(x PRIMARY KEY, y); - } - 2 { - CREATE TABLE t1(b, a PRIMARY KEY); - CREATE TABLE t2(x PRIMARY KEY, y); - } - 3 { - CREATE TABLE t1(b, a); - CREATE UNIQUE INDEX i1 ON t1(a) COVERING (b, a); - CREATE TABLE t2(x PRIMARY KEY, y); - } - 4 { - CREATE TABLE t1(b, a); - CREATE UNIQUE INDEX i1 ON t1(a) COVERING (a, b); - CREATE TABLE t2(y, x PRIMARY KEY); - } -} { - reset_db - - do_execsql_test 90.$tn.0 $schema - - do_execsql_test 90.$tn.1 { - INSERT INTO t2(x, y) VALUES(1, 'one'); - INSERT INTO t2(x, y) VALUES(2, 'two'); - INSERT INTO t2(x, y) VALUES(3, 'three'); - INSERT INTO t2(x, y) VALUES(4, 'four'); - INSERT INTO t2(x, y) VALUES(5, 'five'); - INSERT INTO t2(x, y) VALUES(6, 'six'); - - INSERT INTO t1(a, b) VALUES(2, 'two'); - INSERT INTO t1(a, b) VALUES(3, 'three'); - INSERT INTO t1(a, b) VALUES(5, 'five'); - } - - do_execsql_test 90.$tn.2 { - SELECT y FROM t2 WHERE x IN (SELECT a FROM t1); - } {two three five} - - do_test 90.$tn.3 { - nEphemeral "SELECT y FROM t2 WHERE x IN (SELECT a FROM t1)" - } 0 -} - finish_test Index: test/subquery.test ================================================================== --- test/subquery.test +++ test/subquery.test @@ -239,15 +239,12 @@ SELECT * FROM t4 WHERE x IN (SELECT a FROM t3); } } {10.0} do_test subquery-2.5.3.2 { # Verify that the t4i index was not used in the previous query - execsql { - EXPLAIN QUERY PLAN - SELECT * FROM t4 WHERE x IN (SELECT a FROM t3); - } -} {/SCAN TABLE t4/} + set ::sqlite_query_plan +} {t4 {}} do_test subquery-2.5.4 { execsql { DROP TABLE t3; DROP TABLE t4; } @@ -332,17 +329,16 @@ execsql { SELECT a, (SELECT count(*) FROM t2 WHERE a=c) FROM t1; } } {1 1 2 1} - #------------------------------------------------------------------ # These tests - subquery-4.* - use the TCL statement cache to try # and expose bugs to do with re-using statements that have been # passed to sqlite4_reset(). # -# One problem was that VDBE memory cells were not being initialized +# One problem was that VDBE memory cells were not being initialised # to NULL on the second and subsequent executions. # do_test subquery-4.1.1 { execsql { SELECT (SELECT a FROM t1); Index: test/test_main.c ================================================================== --- test/test_main.c +++ test/test_main.c @@ -1497,11 +1497,11 @@ Tcl_Obj *pDel; }; typedef struct TestNeededX TestNeededX; static void testCollationNeeded(void *pCtx, sqlite4 *db, const char *zReq){ - TestNeededX *p = (TestNeededX *)pCtx; + TestNeededX *p = (TestCollationX *)pCtx; Tcl_Obj *pScript; int rc; pScript = Tcl_DuplicateObj(p->pNeeded); Tcl_IncrRefCount(pScript); @@ -2923,12 +2923,11 @@ if( sqlite4TestErrCode(interp, db, rc) ) return TCL_ERROR; if( objc>=5 ){ const char *zTail = &zSql[nUsed]; int nTail = -1; if( bytes>=0 ){ - nTail = (bytes - nUsed); - if( nTail>strlen(zTail) ) nTail = strlen(zTail); + nTail = bytes - nUsed; } Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, nTail), 0); } if( rc!=SQLITE4_OK ){ assert( pStmt==0 ); @@ -4101,54 +4100,10 @@ } sqlite4_test_control(SQLITE4_TESTCTRL_OPTIMIZATIONS, db, mask); return TCL_OK; } -/* -** Usage: sqlite4_column_text STMT column -** -** Usage: sqlite4_column_decltype STMT column -** -** Usage: sqlite4_column_name STMT column -*/ -static int test_stmt_utf16( - void * clientData, /* Pointer to SQLite API function to be invoked */ - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifndef SQLITE4_OMIT_UTF16 - sqlite4_stmt *pStmt; - int col; - Tcl_Obj *pRet; - const void *zName16; - const void *(*xFunc)(sqlite4_stmt*, int, int*); - int dummy; - - xFunc = (const void *(*)(sqlite4_stmt*, int, int*))clientData; - if( objc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " STMT column", 0); - return TCL_ERROR; - } - - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; - - zName16 = xFunc(pStmt, col, &dummy); - if( zName16 ){ - int n; - const char *z = zName16; - for(n=0; z[n] || z[n+1]; n+=2){} - pRet = Tcl_NewByteArrayObj(zName16, n+2); - Tcl_SetObjResult(interp, pRet); - } -#endif /* SQLITE4_OMIT_UTF16 */ - - return TCL_OK; -} - void sqlite4TestInit(Tcl_Interp *interp){ Sqlitetest_auth_init(interp); Sqlitetest_num_init(interp); Sqlitetest_func_Init(interp); } @@ -4269,14 +4224,10 @@ { "sqlite4_column_database_name",test_stmt_utf8,(void*)sqlite4_column_database_name}, { "sqlite4_column_table_name",test_stmt_utf8,(void*)sqlite4_column_table_name}, { "sqlite4_column_origin_name",test_stmt_utf8,(void*)sqlite4_column_origin_name}, #endif -#ifndef SQLITE4_OMIT_UTF16 - { "sqlite4_column_text16", test_stmt_utf16, (void*)sqlite4_column_text16}, -#endif - { "sqlite4_create_collation", test_create_collation, 0 }, { "sqlite4_collation_needed", test_collation_needed, 0 }, { "sqlite4_profile", test_profile, 0 }, { "sqlite4_trace", test_trace, 0 }, { "working_64bit_int", working_64bit_int, 0 }, @@ -4312,10 +4263,12 @@ #ifdef SQLITE4_DEBUG extern int sqlite4WhereTrace; extern int sqlite4OSTrace; #endif #ifdef SQLITE4_TEST + extern char sqlite4_query_plan[]; + static char *query_plan = sqlite4_query_plan; #ifdef SQLITE4_ENABLE_FTS3 extern int sqlite4_fts3_enable_parentheses; #endif #endif @@ -4349,10 +4302,14 @@ (char*)&sqlite4_xferopt_count, TCL_LINK_INT); #if SQLITE4_OS_WIN Tcl_LinkVar(interp, "sqlite_os_type", (char*)&sqlite4_os_type, TCL_LINK_INT); #endif +#ifdef SQLITE4_TEST + Tcl_LinkVar(interp, "sqlite_query_plan", + (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY); +#endif #ifdef SQLITE4_DEBUG Tcl_LinkVar(interp, "sqlite_where_trace", (char*)&sqlite4WhereTrace, TCL_LINK_INT); #endif Tcl_LinkVar(interp, "sqlite_static_bind_value", Index: test/test_mem.c ================================================================== --- test/test_mem.c +++ test/test_mem.c @@ -13,10 +13,12 @@ #include #include #include "sqliteInt.h" #include "testInt.h" + +#define MIN(x,y) ((x)<(y) ? (x) : (y)) #if defined(__GLIBC__) extern int backtrace(void**,int); extern void backtrace_symbols_fd(void*const*,int,int); # define TM_BACKTRACE 12 Index: test/tester.tcl ================================================================== --- test/tester.tcl +++ test/tester.tcl @@ -493,30 +493,17 @@ if {[catch {uplevel #0 "$cmd;\n"} result]} { puts "\nError: $result" fail_test $name } else { if {[regexp {^~?/.*/$} $expected]} { - # "expected" is of the form "/PATTERN/" then the result if correct if - # regular expression PATTERN matches the result. "~/PATTERN/" means - # the regular expression must not match. if {[string index $expected 0]=="~"} { set re [string map {# {[-0-9.]+}} [string range $expected 2 end-1]] set ok [expr {![regexp $re $result]}] } else { set re [string map {# {[-0-9.]+}} [string range $expected 1 end-1]] set ok [regexp $re $result] } - } elseif {[regexp {^~?\*.*\*$} $expected]} { - # "expected" is of the form "*GLOB*" then the result if correct if - # glob pattern GLOB matches the result. "~/GLOB/" means - # the glob must not match. - if {[string index $expected 0]=="~"} { - set e [string range $expected 1 end] - set ok [expr {![string match $e $result]}] - } else { - set ok [string match $expected $result] - } } else { set ok [expr {[string compare $result $expected]==0}] } if {!$ok} { # if {![info exists ::testprefix] || $::testprefix eq ""} { @@ -1395,11 +1382,11 @@ proc drop_all_tables {{db db}} { ifcapable trigger&&foreignkey { set pk [$db one "PRAGMA foreign_keys"] $db eval "PRAGMA foreign_keys = OFF" } - foreach {idx name} [db eval {PRAGMA database_list}] { + foreach {idx name file} [db eval {PRAGMA database_list}] { if {$idx==1} { set master sqlite_temp_master } else { set master $name.sqlite_master } Index: test/tkt3442.test ================================================================== --- test/tkt3442.test +++ test/tkt3442.test @@ -47,20 +47,20 @@ # and verify that the query plan is the same. # ifcapable explain { do_test tkt3442-1.2 { EQP { SELECT node FROM listhash WHERE id='5000' LIMIT 1; } - } {0 0 0 {SEARCH TABLE listhash USING INDEX ididx (id=?)}} + } {0 0 0 {SEARCH TABLE listhash USING INDEX ididx (id=?) (~1 rows)}} } # Some extra tests testing other permutations of 5000. # ifcapable explain { do_test tkt3442-1.4 { EQP { SELECT node FROM listhash WHERE id=5000 LIMIT 1; } - } {0 0 0 {SEARCH TABLE listhash USING INDEX ididx (id=?)}} + } {0 0 0 {SEARCH TABLE listhash USING INDEX ididx (id=?) (~1 rows)}} } do_test tkt3442-1.5 { catchsql { SELECT node FROM listhash WHERE id=[5000] LIMIT 1; } Index: test/where.test ================================================================== --- test/where.test +++ test/where.test @@ -61,38 +61,39 @@ set res [execsql $sql] #puts "sql={$sql} seek=[kvwrap seek] step=[kvwrap step]" return [concat $res [expr [kvwrap step] + [kvwrap seek]]] } -# Verify that queries use an index. By verifing that the KVWrap layer -# xNext/xPrev/xSeek count is small we can be assured that indices are -# being used properly. +# Verify that queries use an index. We are using the special variable +# "sqlite_search_count" which tallys the number of executions of MoveTo +# and Next operators in the VDBE. By verifing that the search count is +# small we can be assured that indices are being used properly. # do_test where-1.1.1 { count {SELECT x, y, w FROM t1 WHERE w=10} } {3 121 10 3} -do_eqp_test where-1.1.2 { - SELECT x, y, w FROM t1 WHERE w=10 -} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*} +do_test where-1.1.2 { + set sqlite_query_plan +} {t1 i1w} do_test where-1.1.3 { db status step } {0} do_test where-1.1.4 { db eval {SELECT x, y, w FROM t1 WHERE +w=10} } {3 121 10} do_test where-1.1.5 { db status step } {99} -do_eqp_test where-1.1.6 { - SELECT x, y, w FROM t1 WHERE +w=10 -} {*SCAN TABLE t1*} +do_test where-1.1.6 { + set sqlite_query_plan +} {t1 {}} do_test where-1.1.7 { count {SELECT x, y, w AS abc FROM t1 WHERE abc=10} } {3 121 10 3} -do_eqp_test where-1.1.8 { - SELECT x, y, w AS abc FROM t1 WHERE abc=10 -} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*} +do_test where-1.1.8 { + set sqlite_query_plan +} {t1 i1w} do_test where-1.1.9 { db status step } {0} do_test where-1.2.1 { count {SELECT x, y, w FROM t1 WHERE w=11} @@ -107,50 +108,50 @@ count {SELECT x, y, w AS abc FROM t1 WHERE 11=abc} } {3 144 11 3} do_test where-1.4.1 { count {SELECT w, x, y FROM t1 WHERE 11=w AND x>2} } {11 3 144 3} -do_eqp_test where-1.4.2 { - SELECT w, x, y FROM t1 WHERE 11=w AND x>2 -} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*} +do_test where-1.4.2 { + set sqlite_query_plan +} {t1 i1w} do_test where-1.4.3 { count {SELECT w AS a, x AS b, y FROM t1 WHERE 11=a AND b>2} } {11 3 144 3} -do_eqp_test where-1.4.4 { - SELECT w AS a, x AS b, y FROM t1 WHERE 11=a AND b>2 -} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*} +do_test where-1.4.4 { + set sqlite_query_plan +} {t1 i1w} do_test where-1.5 { count {SELECT x, y FROM t1 WHERE y<200 AND w=11 AND x>2} } {3 144 3} -do_eqp_test where-1.5.2 { - SELECT x, y FROM t1 WHERE y<200 AND w=11 AND x>2 -} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*} +do_test where-1.5.2 { + set sqlite_query_plan +} {t1 i1w} do_test where-1.6 { count {SELECT x, y FROM t1 WHERE y<200 AND x>2 AND w=11} } {3 144 3} do_test where-1.7 { count {SELECT x, y FROM t1 WHERE w=11 AND y<200 AND x>2} } {3 144 3} do_test where-1.8 { count {SELECT x, y FROM t1 WHERE w>10 AND y=144 AND x=3} } {3 144 3} -do_eqp_test where-1.8.2 { - SELECT x, y FROM t1 WHERE w>10 AND y=144 AND x=3 -} {*SEARCH TABLE t1 USING INDEX i1xy (x=? AND y=?)*} -do_eqp_test where-1.8.3 { - SELECT x, y FROM t1 WHERE y=144 AND x=3 -} {*SEARCH TABLE t1 USING INDEX i1xy (x=? AND y=?)*} +do_test where-1.8.2 { + set sqlite_query_plan +} {t1 i1xy} +do_test where-1.8.3 { + count {SELECT x, y FROM t1 WHERE y=144 AND x=3} + set sqlite_query_plan +} {t1 i1xy} do_test where-1.9 { count {SELECT x, y FROM t1 WHERE y=144 AND w>10 AND x=3} } {3 144 3} do_test where-1.10 { count {SELECT x, y FROM t1 WHERE x=3 AND w>=10 AND y=121} } {3 121 3} do_test where-1.11 { count {SELECT x, y FROM t1 WHERE x=3 AND y=100 AND w<10} } {3 100 3} - # New for SQLite version 2.1: Verify that that inequality constraints # are used correctly. # do_test where-1.12 { @@ -478,11 +479,11 @@ do_test where-6.1 { execsql { CREATE TABLE t3(a,b,c); CREATE INDEX t3a ON t3(a); CREATE INDEX t3bc ON t3(b,c); - CREATE INDEX t3acb ON t3(a,c,b) COVERING(a,b,c); + CREATE INDEX t3acb ON t3(a,c,b); INSERT INTO t3 SELECT w, 101-w, y FROM t1; SELECT count(*), sum(a), sum(b), sum(c) FROM t3; } } {100 5050 5050 348550} do_test where-6.2 { @@ -511,21 +512,23 @@ SELECT * FROM t3 WHERE a>0 ORDER BY a LIMIT 3 } } {1 100 4 2 99 9 3 98 16 nosort} do_test where-6.7 { + # UPDATE: src4 does a sort here. It picks a different index because it + # does not support the covering index optimization. cksort { SELECT * FROM t3 WHERE b>0 ORDER BY a LIMIT 3 } -} {1 100 4 2 99 9 3 98 16 nosort} +} {1 100 4 2 99 9 3 98 16 sort} ifcapable subquery { do_test where-6.8 { cksort { SELECT * FROM t3 WHERE a IN (3,5,7,1,9,4,2) ORDER BY a LIMIT 3 } - } {1 100 4 2 99 9 3 98 16 nosort} + } {1 100 4 2 99 9 3 98 16 sort} } do_test where-6.9.1 { cksort { SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a LIMIT 3 } @@ -1097,16 +1100,16 @@ INSERT INTO t8 VALUES(4,'four'); } cksort { SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.a, y.b } -} {1/4 1/1 4/4 4/1 nosort} +} {1/4 1/1 4/4 4/1 sort} do_test where-14.2 { cksort { SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.a, y.b DESC } -} {1/1 1/4 4/1 4/4 nosort} +} {1/1 1/4 4/1 4/4 sort} do_test where-14.3 { cksort { SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.a, x.b } } {1/1 1/4 4/1 4/4 nosort} Index: test/where7.test ================================================================== --- test/where7.test +++ test/where7.test @@ -23330,19 +23330,19 @@ CREATE INDEX t302_c8_c3 on t302(c8, c3); CREATE INDEX t302_c5 on t302(c5); EXPLAIN QUERY PLAN SELECT t302.c1 - FROM t302 JOIN t301 ON t302.c8 = +t301.c8 + FROM t302 JOIN t301 ON t302.c8 = t301.c8 WHERE t302.c2 = 19571 AND t302.c3 > 1287603136 AND (t301.c4 = 1407449685622784 OR t301.c8 = 1407424651264000) ORDER BY t302.c5 LIMIT 200; } { - 0 0 1 {SEARCH TABLE t301 USING INDEX t301_c4 (c4=?)} - 0 0 1 {SEARCH TABLE t301 USING PRIMARY KEY (c8=?)} - 0 1 0 {SEARCH TABLE t302 USING INDEX t302_c8_c3 (c8=? AND c3>?)} + 0 0 1 {SEARCH TABLE t301 USING INDEX t301_c4 (c4=?) (~5 rows)} + 0 0 1 {SEARCH TABLE t301 USING PRIMARY KEY (c8=?) (~1 rows)} + 0 1 0 {SEARCH TABLE t302 USING INDEX t302_c8_c3 (c8=? AND c3>?) (~2 rows)} 0 0 0 {USE TEMP B-TREE FOR ORDER BY} } finish_test Index: test/where8.test ================================================================== --- test/where8.test +++ test/where8.test @@ -217,11 +217,11 @@ do_test where8-3.5 { execsql_status { SELECT a, d FROM t1, t2 WHERE (a = 2 OR a = 3) AND (d = a OR e = 'sixteen') } -} {2 2 3 3 2 4 3 4 0 0} +} {2 2 2 4 3 3 3 4 0 0} do_test where8-3.6 { # The first part of the WHERE clause in this query, (a=2 OR a=3) is # transformed into "a IN (2, 3)". This is why the sort is required. # @@ -254,11 +254,11 @@ SELECT a, d FROM t1, t2 WHERE (a = 2 OR b = 'three' OR c = 'IX') AND (d = a OR e = 'sixteen') ORDER BY t1.rowid } -} {2 2 2 4 3 3 3 4 9 9 9 4 9 0 seek=13 step=16} +} {2 2 2 4 3 3 3 4 9 9 9 4 0 0 seek=13 step=16} do_test where8-3.10 { execsql_status { SELECT d FROM t2 WHERE e IS NULL OR e = 'four' } } {1 3 5 10 2 0 0} @@ -270,11 +270,11 @@ } {1 1 2 2 3 3 4 2 4 4 0 0} do_test where8-3.12 { execsql_status { SELECT a, d FROM t1, t2 WHERE (a=d OR b=e) AND +a<5 ORDER BY a } -} {1 1 2 2 3 3 4 2 4 4 9 0} +} {1 1 2 2 3 3 4 2 4 4 0 0} do_test where8-3.13 { execsql_status { SELECT a, d FROM t1, t2 WHERE (a=d OR b=e) AND +a<5 } } {1 1 2 2 3 3 4 2 4 4 9 0} Index: tool/mkkeywordhash.c ================================================================== --- tool/mkkeywordhash.c +++ tool/mkkeywordhash.c @@ -160,11 +160,10 @@ { "COLLATE", "TK_COLLATE", ALWAYS }, { "COLUMN", "TK_COLUMNKW", ALTER }, { "COMMIT", "TK_COMMIT", ALWAYS }, { "CONFLICT", "TK_CONFLICT", CONFLICT }, { "CONSTRAINT", "TK_CONSTRAINT", ALWAYS }, - { "COVERING", "TK_COVERING", ALWAYS }, { "CREATE", "TK_CREATE", ALWAYS }, { "CROSS", "TK_JOIN_KW", ALWAYS }, { "CURRENT_DATE", "TK_CTIME_KW", ALWAYS }, { "CURRENT_TIME", "TK_CTIME_KW", ALWAYS }, { "CURRENT_TIMESTAMP","TK_CTIME_KW", ALWAYS }, Index: tool/mksqlite4c.tcl ================================================================== --- tool/mksqlite4c.tcl +++ tool/mksqlite4c.tcl @@ -217,16 +217,16 @@ global.c env.c ctime.c status.c date.c - math.c os.c fault.c mem.c mem0.c + mem1.c mem2.c mem3.c mem5.c mutex.c mutex_noop.c Index: www/data_encoding.wiki ================================================================== --- www/data_encoding.wiki +++ www/data_encoding.wiki @@ -13,51 +13,31 @@ initial varint itself is not considered part of the header. The header is composed of one or two varints for each column in the table. The varints determines the datatype and size of the value for that column:
-
Encoding
Name
Header
Code (N)
Bytes of
Payload -
Description -
NULL 0 0 NULL -
ZERO 1 0 Zero -
ONE 2 0 One -
INT 3..10 N-2 Signed integer -
NUM 11..21 N-9 Floating-point number -
STRING 22+4*K K String -
BLOB 23+4*K K Inline blob -
KEY 24+4*K 0 Content in key at offset K/2. - Floating-point if LSB of K is 1. -
TYPED 25+4*K K Typed blob, followed by a - single varint type code +
0 NULL +
1 zero +
2 one +
3..10 (N-2)-byte signed integer +
11..21 (N-9)-byte number (two varints: min 2, max 12 bytes) +
22+3*K K-byte string +
23+3*K K-byte inline blob +
24+3*K K-byte typed blob, followed by a single varint type code
-Header codes NULL, ZERO, and ONE are self describing and have no content in the -payload area. - -Strings (STRING) can be either UTF8, UTF16le, or UTF16be. If the first byte of the +Strings can be either UTF8, UTF16le, or UTF16be. If the first byte of the payload is 0x00, 0x01, or 0x02 then that byte is ignored and the remaining bytes are UTF8, UTF16le, or UTF16be respectively. If the first byte is 0x03 -or larger, then the entire string including the first byte is UTF8. An empty -string consists of the header code 22 and no payload. - -Blobs (BLOB) are stored as a sequence of bytes with no encoding. An empty blob -is header code 23. A one-byte blob is header code 27. And so forth. - -The KEY header code indicates that the actually content of the column is in the -key portion of the key/value pair at an offset of K/2 bytes from the beginning of -the key. Numeric values should be interpreted as floating point if K is odd and -as integers if K is even. - -A "typed blob" (TYPED) is a sequence of bytes in an application-defined type. +or larger, then the entire string including the first byte is UTF8. + +A "typed blob" is a sequence of bytes in an application-defined type. The type is determined by a varint that immediately follows the initial varint. Hence, a typed blob uses two varints in the header whereas all other types use a single varint. -The content of INT is the specified number of bytes for the signed integer. -The most significant bytes are first. - -The content of a number (NUM) is two varints. The first varint has a value +The content of a number is two varints. The first varint has a value which is abs(e)*4 + (e<0)*2 + (m<0). The second varint is abs(m). The maximum e is 999, which gives a max varint value of 3999 or 0xf906af, for a maximum first varint size of 3. Values of e greater than 999 (used for Inf and NaN) are represented as a -0. The second varint can be a full 9 bytes. Example values: @@ -76,5 +56,6 @@
0 external blob
1 big int
2 date/time
+ Index: www/key_encoding.wiki ================================================================== --- www/key_encoding.wiki +++ www/key_encoding.wiki @@ -4,11 +4,11 @@ such that memcmp() can be used to sort the keys into their proper order. A key consists of a table number followed by a list of one or more SQL values. Each SQL value in the list has one of the following types: NULL, numeric, text, or binary. Keys are compared value by value, from left to -right, until a difference is found. The first difference determines the +right, until a difference if found. The first difference determines the key order. The table number is a [./varint.wiki | varint] that identifies the table to which the key belongs. Table numbers always sort in ASCENDING order. Index: www/porting.wiki ================================================================== --- www/porting.wiki +++ www/porting.wiki @@ -77,15 +77,6 @@ } /* Free the contents of the buffer (and hence pError) */ sqlite4_buffer_clear(&buf); - -

CHECK Constraint Evaluation

- -

-In SQLite4, CHECK constraints are evaluated after affinities are applied -to new column values. In SQLite3, the CHECK constraints are evaluated before -affinities are applied. - -