1
0
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:
drh
2002-07-05 21:42:36 +00:00
parent 2f2c01e51d
commit 38640e15af
12 changed files with 213 additions and 81 deletions

View File

@@ -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++){