mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-14 00:22:38 +03:00
Progress toward CREATE VIRTUAL TABLE. Still not even close to working... (CVS 3211)
FossilOrigin-Name: 898ec36b4102aaa03979f8f5c510936e57e2ae48
This commit is contained in:
96
src/select.c
96
src/select.c
@@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle SELECT statements in SQLite.
|
||||
**
|
||||
** $Id: select.c,v 1.313 2006/04/26 17:39:34 drh Exp $
|
||||
** $Id: select.c,v 1.314 2006/06/11 23:41:56 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -72,9 +72,9 @@ Select *sqlite3SelectNew(
|
||||
pNew->pOffset = pOffset;
|
||||
pNew->iLimit = -1;
|
||||
pNew->iOffset = -1;
|
||||
pNew->addrOpenVirt[0] = -1;
|
||||
pNew->addrOpenVirt[1] = -1;
|
||||
pNew->addrOpenVirt[2] = -1;
|
||||
pNew->addrOpenEphm[0] = -1;
|
||||
pNew->addrOpenEphm[1] = -1;
|
||||
pNew->addrOpenEphm[2] = -1;
|
||||
if( pNew==&standin) {
|
||||
clearSelect(pNew);
|
||||
pNew = 0;
|
||||
@@ -522,7 +522,7 @@ static int selectInnerLoop(
|
||||
/* Store the result as data using a unique key.
|
||||
*/
|
||||
case SRT_Table:
|
||||
case SRT_VirtualTab: {
|
||||
case SRT_EphemTab: {
|
||||
sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
|
||||
if( pOrderBy ){
|
||||
pushOntoSorter(pParse, pOrderBy, p);
|
||||
@@ -705,7 +705,7 @@ static void generateSortTail(
|
||||
sqlite3VdbeAddOp(v, OP_Column, iTab, pOrderBy->nExpr + 1);
|
||||
switch( eDest ){
|
||||
case SRT_Table:
|
||||
case SRT_VirtualTab: {
|
||||
case SRT_EphemTab: {
|
||||
sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Insert, iParm, 0);
|
||||
@@ -1201,11 +1201,11 @@ static int prepSelectStmt(Parse *pParse, Select *p){
|
||||
if( pTab==0 ){
|
||||
return 1;
|
||||
}
|
||||
/* The isTransient flag indicates that the Table structure has been
|
||||
/* The isEphem flag indicates that the Table structure has been
|
||||
** dynamically allocated and may be freed at any time. In other words,
|
||||
** pTab is not pointing to a persistent table structure that defines
|
||||
** part of the schema. */
|
||||
pTab->isTransient = 1;
|
||||
pTab->isEphem = 1;
|
||||
#endif
|
||||
}else{
|
||||
/* An ordinary table or view name in the FROM clause */
|
||||
@@ -1538,10 +1538,10 @@ static void createSortingIndex(Parse *pParse, Select *p, ExprList *pOrderBy){
|
||||
int addr;
|
||||
assert( pOrderBy->iECursor==0 );
|
||||
pOrderBy->iECursor = pParse->nTab++;
|
||||
addr = sqlite3VdbeAddOp(pParse->pVdbe, OP_OpenVirtual,
|
||||
addr = sqlite3VdbeAddOp(pParse->pVdbe, OP_OpenEphemeral,
|
||||
pOrderBy->iECursor, pOrderBy->nExpr+1);
|
||||
assert( p->addrOpenVirt[2] == -1 );
|
||||
p->addrOpenVirt[2] = addr;
|
||||
assert( p->addrOpenEphm[2] == -1 );
|
||||
p->addrOpenEphm[2] = addr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1647,10 +1647,10 @@ static int multiSelect(
|
||||
|
||||
/* Create the destination temporary table if necessary
|
||||
*/
|
||||
if( eDest==SRT_VirtualTab ){
|
||||
if( eDest==SRT_EphemTab ){
|
||||
assert( p->pEList );
|
||||
assert( nSetP2<sizeof(aSetP2)/sizeof(aSetP2[0]) );
|
||||
aSetP2[nSetP2++] = sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, 0);
|
||||
aSetP2[nSetP2++] = sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, 0);
|
||||
eDest = SRT_Table;
|
||||
}
|
||||
|
||||
@@ -1712,14 +1712,14 @@ static int multiSelect(
|
||||
rc = 1;
|
||||
goto multi_select_end;
|
||||
}
|
||||
addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, unionTab, 0);
|
||||
addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, unionTab, 0);
|
||||
if( priorOp==SRT_Table ){
|
||||
assert( nSetP2<sizeof(aSetP2)/sizeof(aSetP2[0]) );
|
||||
aSetP2[nSetP2++] = addr;
|
||||
}else{
|
||||
assert( p->addrOpenVirt[0] == -1 );
|
||||
p->addrOpenVirt[0] = addr;
|
||||
p->pRightmost->usesVirt = 1;
|
||||
assert( p->addrOpenEphm[0] == -1 );
|
||||
p->addrOpenEphm[0] = addr;
|
||||
p->pRightmost->usesEphm = 1;
|
||||
}
|
||||
createSortingIndex(pParse, p, pOrderBy);
|
||||
assert( p->pEList );
|
||||
@@ -1808,10 +1808,10 @@ static int multiSelect(
|
||||
}
|
||||
createSortingIndex(pParse, p, pOrderBy);
|
||||
|
||||
addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, tab1, 0);
|
||||
assert( p->addrOpenVirt[0] == -1 );
|
||||
p->addrOpenVirt[0] = addr;
|
||||
p->pRightmost->usesVirt = 1;
|
||||
addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, tab1, 0);
|
||||
assert( p->addrOpenEphm[0] == -1 );
|
||||
p->addrOpenEphm[0] = addr;
|
||||
p->pRightmost->usesEphm = 1;
|
||||
assert( p->pEList );
|
||||
|
||||
/* Code the SELECTs to our left into temporary table "tab1".
|
||||
@@ -1823,9 +1823,9 @@ static int multiSelect(
|
||||
|
||||
/* Code the current SELECT into temporary table "tab2"
|
||||
*/
|
||||
addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, tab2, 0);
|
||||
assert( p->addrOpenVirt[1] == -1 );
|
||||
p->addrOpenVirt[1] = addr;
|
||||
addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, tab2, 0);
|
||||
assert( p->addrOpenEphm[1] == -1 );
|
||||
p->addrOpenEphm[1] = addr;
|
||||
p->pPrior = 0;
|
||||
pLimit = p->pLimit;
|
||||
p->pLimit = 0;
|
||||
@@ -1899,7 +1899,7 @@ static int multiSelect(
|
||||
** SELECT might also skip this part if it has no ORDER BY clause and
|
||||
** no temp tables are required.
|
||||
*/
|
||||
if( pOrderBy || p->usesVirt ){
|
||||
if( pOrderBy || p->usesEphm ){
|
||||
int i; /* Loop counter */
|
||||
KeyInfo *pKeyInfo; /* Collating sequence for the result set */
|
||||
Select *pLoop; /* For looping through SELECT statements */
|
||||
@@ -1925,11 +1925,11 @@ static int multiSelect(
|
||||
|
||||
for(pLoop=p; pLoop; pLoop=pLoop->pPrior){
|
||||
for(i=0; i<2; i++){
|
||||
int addr = pLoop->addrOpenVirt[i];
|
||||
int addr = pLoop->addrOpenEphm[i];
|
||||
if( addr<0 ){
|
||||
/* If [0] is unused then [1] is also unused. So we can
|
||||
** always safely abort as soon as the first unused slot is found */
|
||||
assert( pLoop->addrOpenVirt[1]<0 );
|
||||
assert( pLoop->addrOpenEphm[1]<0 );
|
||||
break;
|
||||
}
|
||||
sqlite3VdbeChangeP2(v, addr, nCol);
|
||||
@@ -1959,8 +1959,8 @@ static int multiSelect(
|
||||
*pSortOrder = pOTerm->sortOrder;
|
||||
}
|
||||
assert( p->pRightmost==p );
|
||||
assert( p->addrOpenVirt[2]>=0 );
|
||||
addr = p->addrOpenVirt[2];
|
||||
assert( p->addrOpenEphm[2]>=0 );
|
||||
addr = p->addrOpenEphm[2];
|
||||
sqlite3VdbeChangeP2(v, addr, p->pEList->nExpr+2);
|
||||
pKeyInfo->nField = nOrderByExpr;
|
||||
sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
|
||||
@@ -2394,8 +2394,8 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
|
||||
|
||||
/* If the output is destined for a temporary table, open that table.
|
||||
*/
|
||||
if( eDest==SRT_VirtualTab ){
|
||||
sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, 1);
|
||||
if( eDest==SRT_EphemTab ){
|
||||
sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, 1);
|
||||
}
|
||||
|
||||
/* Generating code to find the min or the max. Basically all we have
|
||||
@@ -2404,7 +2404,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
|
||||
** or last entry in the main table.
|
||||
*/
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
||||
assert( iDb>=0 || pTab->isTransient );
|
||||
assert( iDb>=0 || pTab->isEphem );
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
|
||||
base = pSrc->a[0].iCursor;
|
||||
@@ -2631,7 +2631,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
|
||||
pFunc->iDistinct = -1;
|
||||
}else{
|
||||
KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->pList);
|
||||
sqlite3VdbeOp3(v, OP_OpenVirtual, pFunc->iDistinct, 0,
|
||||
sqlite3VdbeOp3(v, OP_OpenEphemeral, pFunc->iDistinct, 0,
|
||||
(char*)pKeyInfo, P3_KEYINFO_HANDOFF);
|
||||
}
|
||||
}
|
||||
@@ -2780,7 +2780,7 @@ int sqlite3Select(
|
||||
int isDistinct; /* True if the DISTINCT keyword is present */
|
||||
int distinct; /* Table to use for the distinct set */
|
||||
int rc = 1; /* Value to return from this function */
|
||||
int addrSortIndex; /* Address of an OP_OpenVirtual instruction */
|
||||
int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */
|
||||
AggInfo sAggInfo; /* Information used by aggregate queries */
|
||||
int iEnd; /* Address of the end of the query */
|
||||
|
||||
@@ -2868,7 +2868,7 @@ int sqlite3Select(
|
||||
}else{
|
||||
needRestoreContext = 0;
|
||||
}
|
||||
sqlite3Select(pParse, pItem->pSelect, SRT_VirtualTab,
|
||||
sqlite3Select(pParse, pItem->pSelect, SRT_EphemTab,
|
||||
pItem->iCursor, p, i, &isAgg, 0);
|
||||
if( needRestoreContext ){
|
||||
pParse->zAuthContext = zSavedAuthContext;
|
||||
@@ -2908,7 +2908,7 @@ int sqlite3Select(
|
||||
**
|
||||
** This sorting index might end up being unused if the data can be
|
||||
** extracted in pre-sorted order. If that is the case, then the
|
||||
** OP_OpenVirtual instruction will be changed to an OP_Noop once
|
||||
** OP_OpenEphemeral instruction will be changed to an OP_Noop once
|
||||
** we figure out that the sorting index is not needed. The addrSortIndex
|
||||
** variable is used to facilitate that change.
|
||||
*/
|
||||
@@ -2925,8 +2925,8 @@ int sqlite3Select(
|
||||
}
|
||||
pKeyInfo = keyInfoFromExprList(pParse, pOrderBy);
|
||||
pOrderBy->iECursor = pParse->nTab++;
|
||||
p->addrOpenVirt[2] = addrSortIndex =
|
||||
sqlite3VdbeOp3(v, OP_OpenVirtual, pOrderBy->iECursor, pOrderBy->nExpr+2,
|
||||
p->addrOpenEphm[2] = addrSortIndex =
|
||||
sqlite3VdbeOp3(v, OP_OpenEphemeral, pOrderBy->iECursor, pOrderBy->nExpr+2,
|
||||
(char*)pKeyInfo, P3_KEYINFO_HANDOFF);
|
||||
}else{
|
||||
addrSortIndex = -1;
|
||||
@@ -2934,8 +2934,8 @@ int sqlite3Select(
|
||||
|
||||
/* If the output is destined for a temporary table, open that table.
|
||||
*/
|
||||
if( eDest==SRT_VirtualTab ){
|
||||
sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, pEList->nExpr);
|
||||
if( eDest==SRT_EphemTab ){
|
||||
sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, pEList->nExpr);
|
||||
}
|
||||
|
||||
/* Set the limiter.
|
||||
@@ -2949,7 +2949,7 @@ int sqlite3Select(
|
||||
KeyInfo *pKeyInfo;
|
||||
distinct = pParse->nTab++;
|
||||
pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
|
||||
sqlite3VdbeOp3(v, OP_OpenVirtual, distinct, 0,
|
||||
sqlite3VdbeOp3(v, OP_OpenEphemeral, distinct, 0,
|
||||
(char*)pKeyInfo, P3_KEYINFO_HANDOFF);
|
||||
}else{
|
||||
distinct = -1;
|
||||
@@ -2963,13 +2963,13 @@ int sqlite3Select(
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy);
|
||||
if( pWInfo==0 ) goto select_end;
|
||||
|
||||
/* If sorting index that was created by a prior OP_OpenVirtual
|
||||
** instruction ended up not being needed, then change the OP_OpenVirtual
|
||||
/* 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.
|
||||
*/
|
||||
if( addrSortIndex>=0 && pOrderBy==0 ){
|
||||
sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
|
||||
p->addrOpenVirt[2] = -1;
|
||||
p->addrOpenEphm[2] = -1;
|
||||
}
|
||||
|
||||
/* Use the standard inner loop
|
||||
@@ -3003,7 +3003,7 @@ int sqlite3Select(
|
||||
int addrGroupByChange; /* Code that runs when any GROUP BY term changes */
|
||||
int addrProcessRow; /* Code to process a single input row */
|
||||
int addrEnd; /* End of all processing */
|
||||
int addrSortingIdx; /* The OP_OpenVirtual for the sorting index */
|
||||
int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
|
||||
int addrReset; /* Subroutine for resetting the accumulator */
|
||||
|
||||
addrEnd = sqlite3VdbeMakeLabel(v);
|
||||
@@ -3050,13 +3050,13 @@ int sqlite3Select(
|
||||
|
||||
/* If there is a GROUP BY clause we might need a sorting index to
|
||||
** implement it. Allocate that sorting index now. If it turns out
|
||||
** that we do not need it after all, the OpenVirtual instruction
|
||||
** that we do not need it after all, the OpenEphemeral instruction
|
||||
** will be converted into a Noop.
|
||||
*/
|
||||
sAggInfo.sortingIdx = pParse->nTab++;
|
||||
pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
|
||||
addrSortingIdx =
|
||||
sqlite3VdbeOp3(v, OP_OpenVirtual, sAggInfo.sortingIdx,
|
||||
sqlite3VdbeOp3(v, OP_OpenEphemeral, sAggInfo.sortingIdx,
|
||||
sAggInfo.nSortingColumn,
|
||||
(char*)pKeyInfo, P3_KEYINFO_HANDOFF);
|
||||
|
||||
@@ -3119,7 +3119,7 @@ int sqlite3Select(
|
||||
if( pWInfo==0 ) goto select_end;
|
||||
if( pGroupBy==0 ){
|
||||
/* The optimizer is able to deliver rows in group by order so
|
||||
** we do not have to sort. The OP_OpenVirtual table will be
|
||||
** we do not have to sort. The OP_OpenEphemeral table will be
|
||||
** cancelled later because we still need to use the pKeyInfo
|
||||
*/
|
||||
pGroupBy = p->pGroupBy;
|
||||
|
||||
Reference in New Issue
Block a user