/ Check-in [b959c629]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Alternative implementation of exprCompareVariable().
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | partial-index-variables
Files: files | file ages | folders
SHA3-256:b959c6297c151150ea2dca24aa1f68f3bd76dd6620eb6c03f8dfa59fdd5c13b2
User & Date: drh 2017-06-28 21:47:16
Original Comment: Alternative implementation of exprCompareVariable(). Need to run tests on both this branch and the original to see which one to go with.
Context
2017-06-29
01:23
Fix the exprCompareVariable() routine so that it works for non-UTF8 text. Closed-Leaf check-in: 25acd965 user: drh tags: partial-index-variables
2017-06-28
21:47
Alternative implementation of exprCompareVariable(). check-in: b959c629 user: drh tags: partial-index-variables
18:25
Make the query planners use of partial indexes based on bound variables responsive to the SQLITE_DBCONFIG_ENABLE_QPSG setting. check-in: a934dd14 user: drh tags: partial-index-variables
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685

4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
....
4721
4722
4723
4724
4725
4726
4727




4728
4729
4730
4731
4732

4733
4734
4735
4736
4737
4738
4739
....
4829
4830
4831
4832
4833
4834
4835





4836
4837
4838
4839
4840
4841
4842
** Additionally, if pExpr is a simple SQL value and the value is the
** same as that currently bound to variable pVar, non-zero is returned.
** Otherwise, if the values are not the same or if pExpr is not a simple
** SQL value, zero is returned.
*/
static int exprCompareVariable(Parse *pParse, Expr *pVar, Expr *pExpr){
  int res = 0;
  int iVar = pVar->iColumn;
  Expr *p = pExpr;

  while( p->op==TK_UMINUS ) p = p->pLeft;
  if( p->op==TK_NULL  || p->op==TK_INTEGER 
   || p->op==TK_FLOAT || p->op==TK_STRING 
   || p->op==TK_BLOB 
  ){

    sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
    sqlite3_value *pL;
    pL = sqlite3VdbeGetBoundValue(pParse->pReprepare, iVar, SQLITE_AFF_BLOB);
    if( pL ){
      sqlite3_value *pR = 0;
      sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB,&pR);
      assert( pR || pParse->db->mallocFailed );
      if( pR && 0==sqlite3MemCompare(pL, pR, 0) ){
        res = 1;
      }
      sqlite3ValueFree(pR);
      sqlite3ValueFree(pL);
    }else if( p->op==TK_NULL ){
      res = 1;
    }
  }

  return res;
}

/*
** Do a deep comparison of two expression trees.  Return 0 if the two
................................................................................
** returns 2, then you do not really know for certain if the two
** expressions are the same.  But if you get a 0 or 1 return, then you
** can be sure the expressions are the same.  In the places where
** this routine is used, it does not hurt to get an extra 2 - that
** just might result in some slightly slower code.  But returning
** an incorrect 0 or 1 could lead to a malfunction.
**




** Argument pParse should normally be NULL. If it is not NULL and 
** expression pA contains SQL variable references, then the values
** currently bound to those variable references may be compared to
** simple SQL values in pB. See comments above function exprCompareVariable()
** for details.

*/
int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
  u32 combinedFlags;
  if( pA==0 || pB==0 ){
    return pB==pA ? 0 : 2;
  }
  if( pParse && pA->op==TK_VARIABLE && exprCompareVariable(pParse, pA, pB) ){
................................................................................
**     pE1: x!=?1      pE2: x IS NOT NULL    Result: true
**     pE1: x IS NULL  pE2: x IS NOT NULL    Result: false
**     pE1: x IS ?2    pE2: x IS NOT NULL    Reuslt: false
**
** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has
** Expr.iTable<0 then assume a table number given by iTab.
**





** When in doubt, return false.  Returning true might give a performance
** improvement.  Returning false might cause a performance reduction, but
** it will always give the correct answer and is hence always safe.
*/
int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, int iTab){
  if( sqlite3ExprCompare(pParse, pE1, pE2, iTab)==0 ){
    return 1;







|
|
|
|
<
<
<
|
>

<

<
<
<
<
|
|
|
|
|
<
<
<







 







>
>
>
>
|
<
<
<
<
>







 







>
>
>
>
>







4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681



4682
4683
4684

4685




4686
4687
4688
4689
4690



4691
4692
4693
4694
4695
4696
4697
....
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722




4723
4724
4725
4726
4727
4728
4729
4730
....
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
** Additionally, if pExpr is a simple SQL value and the value is the
** same as that currently bound to variable pVar, non-zero is returned.
** Otherwise, if the values are not the same or if pExpr is not a simple
** SQL value, zero is returned.
*/
static int exprCompareVariable(Parse *pParse, Expr *pVar, Expr *pExpr){
  int res = 0;
  int iVar;
  sqlite3_value *pL, *pR = 0;
  
  sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB, &pR);



  if( pR ){
    iVar = pVar->iColumn;
    sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);

    pL = sqlite3VdbeGetBoundValue(pParse->pReprepare, iVar, SQLITE_AFF_BLOB);




    if( pL && 0==sqlite3MemCompare(pL, pR, 0) ){
      res = 1;
    }
    sqlite3ValueFree(pR);
    sqlite3ValueFree(pL);



  }

  return res;
}

/*
** Do a deep comparison of two expression trees.  Return 0 if the two
................................................................................
** returns 2, then you do not really know for certain if the two
** expressions are the same.  But if you get a 0 or 1 return, then you
** can be sure the expressions are the same.  In the places where
** this routine is used, it does not hurt to get an extra 2 - that
** just might result in some slightly slower code.  But returning
** an incorrect 0 or 1 could lead to a malfunction.
**
** If pParse is not NULL then TK_VARIABLE terms in pA with bindings in
** pParse->pReprepare can be matched against literals in pB.  The 
** pParse->pVdbe->expmask bitmask is updated for each variable referenced.
** If pParse is NULL (the normal case) then any TK_VARIABLE term in 
** Argument pParse should normally be NULL. If it is not NULL and pA or




** pB causes a return value of 2.
*/
int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
  u32 combinedFlags;
  if( pA==0 || pB==0 ){
    return pB==pA ? 0 : 2;
  }
  if( pParse && pA->op==TK_VARIABLE && exprCompareVariable(pParse, pA, pB) ){
................................................................................
**     pE1: x!=?1      pE2: x IS NOT NULL    Result: true
**     pE1: x IS NULL  pE2: x IS NOT NULL    Result: false
**     pE1: x IS ?2    pE2: x IS NOT NULL    Reuslt: false
**
** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has
** Expr.iTable<0 then assume a table number given by iTab.
**
** If pParse is not NULL, then the values of bound variables in pE1 are 
** compared against literal values in pE2 and pParse->pVdbe->expmask is
** modified to record which bound variables are referenced.  If pParse 
** is NULL, then false will be returned if pE1 contains any bound variables.
**
** When in doubt, return false.  Returning true might give a performance
** improvement.  Returning false might cause a performance reduction, but
** it will always give the correct answer and is hence always safe.
*/
int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, int iTab){
  if( sqlite3ExprCompare(pParse, pE1, pE2, iTab)==0 ){
    return 1;