This patch contains the beginnings of the data-typing infrastructure.
The new build-in TypeOf() function is added. New opcodes for doing
pure text comparisons are added. Most changes are disabled pending
the 2.6.0 release. (CVS 632)
FossilOrigin-Name: cbbc858d973c2d515c6a2464981316549a241b73
diff --git a/src/expr.c b/src/expr.c
index e6a3cfa..92ae657 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.72 2002/06/17 17:07:20 drh Exp $
+** $Id: expr.c,v 1.73 2002/06/20 11:36:49 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -460,8 +460,10 @@
if( j==pTab->iPKey ){
/* Substitute the record number for the INTEGER PRIMARY KEY */
pExpr->iColumn = -1;
+ pExpr->dataType = SQLITE_SO_NUM;
}else{
pExpr->iColumn = j;
+ pExpr->dataType = pTab->aCol[j].sortOrder & SQLITE_SO_TYPEMASK;
}
pExpr->op = TK_COLUMN;
}
@@ -485,6 +487,7 @@
pExpr->iTable = base;
cnt = 1 + (pTabList->nSrc>1);
pExpr->op = TK_COLUMN;
+ pExpr->dataType = SQLITE_SO_NUM;
}
sqliteFree(z);
if( cnt==0 && pExpr->token.z[0]!='"' ){
@@ -546,6 +549,7 @@
}else{
pExpr->iColumn = j;
}
+ pExpr->dataType = pTab->aCol[j].sortOrder & SQLITE_SO_TYPEMASK;
}
}
}
@@ -568,10 +572,12 @@
if( t ){
int j;
- for(j=0; j < pTriggerStack->pTab->nCol; j++) {
- if( sqliteStrICmp(pTriggerStack->pTab->aCol[j].zName, zRight)==0 ){
+ Table *pTab = pTriggerStack->pTab;
+ for(j=0; j < pTab->nCol; j++) {
+ if( sqliteStrICmp(pTab->aCol[j].zName, zRight)==0 ){
cnt++;
pExpr->iColumn = j;
+ pExpr->dataType = pTab->aCol[j].sortOrder & SQLITE_SO_TYPEMASK;
}
}
}
@@ -580,6 +586,7 @@
if( cnt==0 && cntTab==1 && sqliteIsRowid(zRight) ){
cnt = 1;
pExpr->iColumn = -1;
+ pExpr->dataType = SQLITE_SO_NUM;
}
sqliteFree(zLeft);
sqliteFree(zRight);
@@ -714,10 +721,11 @@
if( pExpr==0 ) return 0;
switch( pExpr->op ){
case TK_FUNCTION: {
- int n = pExpr->pList ? pExpr->pList->nExpr : 0;
- int no_such_func = 0;
- int wrong_num_args = 0;
- int is_agg = 0;
+ int n = pExpr->pList ? pExpr->pList->nExpr : 0; /* Number of arguments */
+ int no_such_func = 0; /* True if no such function exists */
+ int is_type_of = 0; /* True if is the special TypeOf() function */
+ int wrong_num_args = 0; /* True if wrong number of arguments */
+ int is_agg = 0; /* True if is an aggregate function */
int i;
FuncDef *pDef;
@@ -727,7 +735,12 @@
pDef = sqliteFindFunction(pParse->db,
pExpr->token.z, pExpr->token.n, -1, 0);
if( pDef==0 ){
- no_such_func = 1;
+ if( n==1 && pExpr->token.n==6
+ && sqliteStrNICmp(pExpr->token.z, "typeof", 6)==0 ){
+ is_type_of = 1;
+ }else {
+ no_such_func = 1;
+ }
}else{
wrong_num_args = 1;
}
@@ -758,6 +771,37 @@
nErr = sqliteExprCheck(pParse, pExpr->pList->a[i].pExpr,
allowAgg && !is_agg, pIsAgg);
}
+ if( pDef==0 ){
+ if( is_type_of ){
+ pExpr->op = TK_STRING;
+ if( sqliteExprType(pExpr->pList->a[0].pExpr)==SQLITE_SO_NUM ){
+ pExpr->token.z = "numeric";
+ pExpr->token.n = 7;
+ }else{
+ pExpr->token.z = "text";
+ pExpr->token.n = 4;
+ }
+ }
+ }else if( pDef->dataType>=0 ){
+ if( pDef->dataType<n ){
+ pExpr->dataType =
+ sqliteExprType(pExpr->pList->a[pDef->dataType].pExpr);
+ }else{
+ pExpr->dataType = SQLITE_SO_NUM;
+ }
+ }else if( pDef->dataType==SQLITE_ARGS ){
+ pDef->dataType = SQLITE_SO_TEXT;
+ for(i=0; i<n; i++){
+ if( sqliteExprType(pExpr->pList->a[i].pExpr)==SQLITE_SO_NUM ){
+ pExpr->dataType = SQLITE_SO_NUM;
+ break;
+ }
+ }
+ }else if( pDef->dataType==SQLITE_NUMERIC ){
+ pExpr->dataType = SQLITE_SO_NUM;
+ }else{
+ pExpr->dataType = SQLITE_SO_TEXT;
+ }
}
default: {
if( pExpr->pLeft ){
@@ -781,6 +825,78 @@
}
/*
+** Return either SQLITE_SO_NUM or SQLITE_SO_TEXT to indicate whether the
+** given expression should sort as numeric values or as text.
+**
+** The sqliteExprResolveIds() and sqliteExprCheck() routines must have
+** both been called on the expression before it is passed to this routine.
+*/
+int sqliteExprType(Expr *p){
+ if( p==0 ) return SQLITE_SO_NUM;
+ while( p ) switch( p->op ){
+ case TK_PLUS:
+ case TK_MINUS:
+ case TK_STAR:
+ case TK_SLASH:
+ case TK_AND:
+ case TK_OR:
+ case TK_ISNULL:
+ case TK_NOTNULL:
+ case TK_NOT:
+ case TK_UMINUS:
+ case TK_BITAND:
+ case TK_BITOR:
+ case TK_BITNOT:
+ case TK_LSHIFT:
+ case TK_RSHIFT:
+ case TK_REM:
+ case TK_INTEGER:
+ case TK_FLOAT:
+ case TK_IN:
+ case TK_BETWEEN:
+ return SQLITE_SO_NUM;
+
+ case TK_STRING:
+ case TK_NULL:
+ case TK_CONCAT:
+ return SQLITE_SO_TEXT;
+
+ case TK_LT:
+ case TK_LE:
+ case TK_GT:
+ case TK_GE:
+ case TK_NE:
+ case TK_EQ:
+ if( sqliteExprType(p->pLeft)==SQLITE_SO_NUM ){
+ return SQLITE_SO_NUM;
+ }
+ p = p->pRight;
+ break;
+
+ case TK_AS:
+ p = p->pLeft;
+ break;
+
+ case TK_COLUMN:
+ case TK_FUNCTION:
+ case TK_AGG_FUNCTION:
+ return p->dataType;
+
+ case TK_SELECT:
+ assert( p->pSelect );
+ assert( p->pSelect->pEList );
+ assert( p->pSelect->pEList->nExpr>0 );
+ p = p->pSelect->pEList->a[0].pExpr;
+ break;
+
+ default:
+ assert( p->op==TK_ABORT ); /* Can't Happen */
+ break;
+ }
+ return SQLITE_SO_NUM;
+}
+
+/*
** Generate code into the current Vdbe to evaluate the given
** expression and leave the result on the top of stack.
*/
@@ -856,6 +972,17 @@
sqliteVdbeAddOp(v, OP_String, 0, 0);
break;
}
+ case TK_LT:
+ case TK_LE:
+ case TK_GT:
+ case TK_GE:
+ case TK_NE:
+ case TK_EQ: {
+ if( pParse->db->file_format>=3 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){
+ op += 6; /* Convert numeric opcodes to text opcodes */
+ }
+ /* Fall through into the next case */
+ }
case TK_AND:
case TK_OR:
case TK_PLUS:
@@ -864,13 +991,7 @@
case TK_REM:
case TK_BITAND:
case TK_BITOR:
- case TK_SLASH:
- case TK_LT:
- case TK_LE:
- case TK_GT:
- case TK_GE:
- case TK_NE:
- case TK_EQ: {
+ case TK_SLASH: {
sqliteExprCode(pParse, pExpr->pLeft);
sqliteExprCode(pParse, pExpr->pRight);
sqliteVdbeAddOp(v, op, 0, 0);
@@ -1090,6 +1211,9 @@
case TK_EQ: {
sqliteExprCode(pParse, pExpr->pLeft);
sqliteExprCode(pParse, pExpr->pRight);
+ if( pParse->db->file_format>=3 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){
+ op += 6; /* Convert numeric opcodes to text opcodes */
+ }
sqliteVdbeAddOp(v, op, jumpIfNull, dest);
break;
}
@@ -1180,6 +1304,9 @@
case TK_GE:
case TK_NE:
case TK_EQ: {
+ if( pParse->db->file_format>=3 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){
+ op += 6; /* Convert numeric opcodes to text opcodes */
+ }
sqliteExprCode(pParse, pExpr->pLeft);
sqliteExprCode(pParse, pExpr->pRight);
sqliteVdbeAddOp(v, op, jumpIfNull, dest);
@@ -1395,6 +1522,7 @@
if( p==0 && createFlag && (p = sqliteMalloc(sizeof(*p)))!=0 ){
p->nArg = nArg;
p->pNext = pFirst;
+ p->dataType = pFirst ? pFirst->dataType : SQLITE_NUMERIC;
sqliteHashInsert(&db->aFunc, zName, nName, (void*)p);
}
return p;