aboutsummaryrefslogtreecommitdiff
path: root/src/expr.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2009-11-17 18:31:47 +0000
committerdrh <drh@noemail.net>2009-11-17 18:31:47 +0000
commit039fc32e8488cba77d12d1fc5038ce6cfd7dcf40 (patch)
treea3db12f7a3872f1338926b141355ecaea39f91cc /src/expr.c
parent68ff78b1b04bad32f67d5d0bb12c4893d8aedefb (diff)
downloadsqlite-039fc32e8488cba77d12d1fc5038ce6cfd7dcf40.tar.gz
sqlite-039fc32e8488cba77d12d1fc5038ce6cfd7dcf40.zip
Code generator tries to avoid pointless OP_IsNull and OP_Affinity opcodes.
FossilOrigin-Name: ebb0c8a3e977dc741704e733b5a5d931d9b27028
Diffstat (limited to 'src/expr.c')
-rw-r--r--src/expr.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/expr.c b/src/expr.c
index a5e5edd32..db74e8759 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1259,6 +1259,71 @@ int sqlite3ExprIsInteger(Expr *p, int *pValue){
}
/*
+** Return FALSE if there is no chance that the expression can be NULL.
+**
+** If the expression might be NULL or if the expression is too complex
+** to tell return TRUE.
+**
+** This routine is used as an optimization, to skip OP_IsNull opcodes
+** when we know that a value cannot be NULL. Hence, a false positive
+** (returning TRUE when in fact the expression can never be NULL) might
+** be a small performance hit but is otherwise harmless. On the other
+** hand, a false negative (returning FALSE when the result could be NULL)
+** will likely result in an incorrect answer. So when in doubt, return
+** TRUE.
+*/
+int sqlite3ExprCanBeNull(const Expr *p){
+ u8 op;
+ while( p->op==TK_UPLUS || p->op==TK_MINUS ){ p = p->pLeft; }
+ op = p->op;
+ if( op==TK_REGISTER ) op = p->op2;
+ switch( op ){
+ case TK_INTEGER:
+ case TK_STRING:
+ case TK_FLOAT:
+ case TK_BLOB:
+ return 0;
+ default:
+ return 1;
+ }
+}
+
+/*
+** Return TRUE if the given expression is a constant which would be
+** unchanged by OP_Affinity with the affinity given in the second
+** argument.
+**
+** This routine is used to determine if the OP_Affinity operation
+** can be omitted. When in doubt return FALSE. A false negative
+** is harmless. A false positive, however, can result in the wrong
+** answer.
+*/
+int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){
+ u8 op;
+ if( aff==SQLITE_AFF_NONE ) return 1;
+ while( p->op==TK_UPLUS || p->op==TK_MINUS ){ p = p->pLeft; }
+ op = p->op;
+ if( op==TK_REGISTER ) op = p->op2;
+ switch( op ){
+ case TK_INTEGER: {
+ return aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC;
+ }
+ case TK_FLOAT: {
+ return aff==SQLITE_AFF_REAL || aff==SQLITE_AFF_NUMERIC;
+ }
+ case TK_STRING: {
+ return aff==SQLITE_AFF_TEXT;
+ }
+ case TK_BLOB: {
+ return 1;
+ }
+ default: {
+ return 0;
+ }
+ }
+}
+
+/*
** Return TRUE if the given string is a row-id column name.
*/
int sqlite3IsRowid(const char *z){