mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-14 00:22:38 +03:00
All the code is now in place for SQLite to distinguish between NUMERIC and
TEXT datatypes. Still need to turn on the new code and test it. (CVS 659) FossilOrigin-Name: b4737a16c997a6c139d616211fb6bc4b0fae181c
This commit is contained in:
73
src/select.c
73
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.102 2002/06/29 02:20:08 drh Exp $
|
||||
** $Id: select.c,v 1.103 2002/07/05 21:42:37 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -315,7 +315,24 @@ static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){
|
||||
zSortOrder = sqliteMalloc( pOrderBy->nExpr + 1 );
|
||||
if( zSortOrder==0 ) return;
|
||||
for(i=0; i<pOrderBy->nExpr; i++){
|
||||
zSortOrder[i] = pOrderBy->a[i].sortOrder ? '-' : '+';
|
||||
int order = pOrderBy->a[i].sortOrder;
|
||||
int type;
|
||||
int c;
|
||||
if( (order & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){
|
||||
type = SQLITE_SO_TEXT;
|
||||
}else if( (order & SQLITE_SO_TYPEMASK)==SQLITE_SO_NUM ){
|
||||
type = SQLITE_SO_NUM;
|
||||
}else if( pParse->db->file_format>=3 ){
|
||||
type = sqliteExprType(pOrderBy->a[i].pExpr);
|
||||
}else{
|
||||
type = SQLITE_SO_NUM;
|
||||
}
|
||||
if( (order & SQLITE_SO_DIRMASK)==SQLITE_SO_ASC ){
|
||||
c = type==SQLITE_SO_TEXT ? 'A' : '+';
|
||||
}else{
|
||||
c = type==SQLITE_SO_TEXT ? 'D' : '-';
|
||||
}
|
||||
zSortOrder[i] = c;
|
||||
sqliteExprCode(pParse, pOrderBy->a[i].pExpr);
|
||||
}
|
||||
zSortOrder[pOrderBy->nExpr] = 0;
|
||||
@@ -325,13 +342,37 @@ static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){
|
||||
sqliteVdbeAddOp(v, OP_SortPut, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine adds a P3 argument to the last VDBE opcode that was
|
||||
** inserted. The P3 argument added is a string suitable for the
|
||||
** OP_MakeKey or OP_MakeIdxKey opcodes. The string consists of
|
||||
** characters 't' or 'n' depending on whether or not the various
|
||||
** fields of the key to be generated should be treated as numeric
|
||||
** or as text. See the OP_MakeKey and OP_MakeIdxKey opcode
|
||||
** documentation for additional information about the P3 string.
|
||||
** See also the sqliteAddIdxKeyType() routine.
|
||||
*/
|
||||
void sqliteAddKeyType(Vdbe *v, ExprList *pEList){
|
||||
int nColumn = pEList->nExpr;
|
||||
char *zType = sqliteMalloc( nColumn+1 );
|
||||
int i;
|
||||
if( zType==0 ) return;
|
||||
for(i=0; i<nColumn; i++){
|
||||
zType[i] = sqliteExprType(pEList->a[i].pExpr)==SQLITE_SO_NUM ? 'n' : 't';
|
||||
}
|
||||
zType[i] = 0;
|
||||
sqliteVdbeChangeP3(v, -1, zType, nColumn);
|
||||
sqliteFree(zType);
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine generates the code for the inside of the inner loop
|
||||
** of a SELECT.
|
||||
**
|
||||
** The pEList is used to determine the values for each column in the
|
||||
** result row. Except if pEList==NULL, then we just read nColumn
|
||||
** elements from the srcTab table.
|
||||
** If srcTab and nColumn are both zero, then the pEList expressions
|
||||
** are evaluated in order to get the data for this row. If nColumn>0
|
||||
** then data is pulled from srcTab and pEList is used only to get the
|
||||
** datatypes for each column.
|
||||
*/
|
||||
static int selectInnerLoop(
|
||||
Parse *pParse, /* The parser context */
|
||||
@@ -348,7 +389,9 @@ static int selectInnerLoop(
|
||||
){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int i;
|
||||
|
||||
if( v==0 ) return 0;
|
||||
assert( pEList!=0 );
|
||||
|
||||
/* If there was a LIMIT clause on the SELECT statement, then do the check
|
||||
** to see if this row should be output.
|
||||
@@ -366,15 +409,15 @@ static int selectInnerLoop(
|
||||
|
||||
/* Pull the requested columns.
|
||||
*/
|
||||
if( pEList ){
|
||||
for(i=0; i<pEList->nExpr; i++){
|
||||
sqliteExprCode(pParse, pEList->a[i].pExpr);
|
||||
}
|
||||
nColumn = pEList->nExpr;
|
||||
}else{
|
||||
if( nColumn>0 ){
|
||||
for(i=0; i<nColumn; i++){
|
||||
sqliteVdbeAddOp(v, OP_Column, srcTab, i);
|
||||
}
|
||||
}else{
|
||||
nColumn = pEList->nExpr;
|
||||
for(i=0; i<pEList->nExpr; i++){
|
||||
sqliteExprCode(pParse, pEList->a[i].pExpr);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the DISTINCT keyword was present on the SELECT statement
|
||||
@@ -386,6 +429,7 @@ static int selectInnerLoop(
|
||||
sqliteVdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqliteVdbeCurrentAddr(v)+7);
|
||||
#endif
|
||||
sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1);
|
||||
if( pParse->db->file_format>=3 ) sqliteAddKeyType(v, pEList);
|
||||
sqliteVdbeAddOp(v, OP_Distinct, distinct, sqliteVdbeCurrentAddr(v)+3);
|
||||
sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0);
|
||||
sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
|
||||
@@ -1119,7 +1163,7 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
|
||||
iCont = sqliteVdbeMakeLabel(v);
|
||||
sqliteVdbeAddOp(v, OP_Rewind, unionTab, iBreak);
|
||||
iStart = sqliteVdbeCurrentAddr(v);
|
||||
rc = selectInnerLoop(pParse, p, 0, unionTab, p->pEList->nExpr,
|
||||
rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr,
|
||||
p->pOrderBy, -1, eDest, iParm,
|
||||
iCont, iBreak);
|
||||
if( rc ) return 1;
|
||||
@@ -1175,7 +1219,7 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
|
||||
sqliteVdbeAddOp(v, OP_Rewind, tab1, iBreak);
|
||||
iStart = sqliteVdbeAddOp(v, OP_FullKey, tab1, 0);
|
||||
sqliteVdbeAddOp(v, OP_NotFound, tab2, iCont);
|
||||
rc = selectInnerLoop(pParse, p, 0, tab1, p->pEList->nExpr,
|
||||
rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
|
||||
p->pOrderBy, -1, eDest, iParm,
|
||||
iCont, iBreak);
|
||||
if( rc ) return 1;
|
||||
@@ -1547,7 +1591,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
|
||||
eList.a = &eListItem;
|
||||
eList.a[0].pExpr = pExpr;
|
||||
cont = sqliteVdbeMakeLabel(v);
|
||||
selectInnerLoop(pParse, p, &eList, base, 1, 0, -1, eDest, iParm, cont, cont);
|
||||
selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont);
|
||||
sqliteVdbeResolveLabel(v, cont);
|
||||
sqliteVdbeAddOp(v, OP_Close, base, 0);
|
||||
return 1;
|
||||
@@ -1914,6 +1958,7 @@ int sqliteSelect(
|
||||
sqliteExprCode(pParse, pGroupBy->a[i].pExpr);
|
||||
}
|
||||
sqliteVdbeAddOp(v, OP_MakeKey, pGroupBy->nExpr, 0);
|
||||
if( pParse->db->file_format>=3 ) sqliteAddKeyType(v, pGroupBy);
|
||||
lbl1 = sqliteVdbeMakeLabel(v);
|
||||
sqliteVdbeAddOp(v, OP_AggFocus, 0, lbl1);
|
||||
for(i=0; i<pParse->nAgg; i++){
|
||||
|
||||
Reference in New Issue
Block a user