SQLite

Check-in [76cd611d41]
Login

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

Overview
Comment:Smaller and faster implementation of exprMightBeIndexed().
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 76cd611d41465fcec61c21520d55172cb236530f38386b7d4a5544ba87de2353
User & Date: drh 2017-04-11 18:06:48.387
Context
2017-04-11
19:00
Update this branch with latest trunk changes. (check-in: 0f66a09393 user: dan tags: schemalint)
18:55
Limit the depth of recursion for valid JSON in the JSON1 extension in order to avoid using excess stack space in the recursive descent parser. Fix for ticket [981329adeef51011052667a9]. (check-in: 1f68c18459 user: drh tags: trunk)
18:06
Smaller and faster implementation of exprMightBeIndexed(). (check-in: 76cd611d41 user: drh tags: trunk)
16:44
Very slight smaller and faster sqlite3SelectNew() (check-in: 4143650c4c user: drh tags: trunk)
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to src/whereexpr.c.
826
827
828
829
830
831
832
833
834


835
836
837
838
839
840
841
842

843
844
845

846

847
848
849
850
851
852










853












854
855
856
857
858
859
860
861
862
863
864
865
866


867
868
869
870
871
872
873
874
875
876
877
878
879
880

881
882
883
884
885
886
887
888
889
890
891
826
827
828
829
830
831
832


833
834
835
836
837
838
839
840
841

842
843

844
845

846


847
848
849
850
851
852
853
854
855
856
857
858
859
860

861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883


884
885
886
887
888
889










890




891
892
893
894
895
896
897







-
-
+
+







-
+

-

+
-
+
-
-




+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+











-
-
+
+




-
-
-
-
-
-
-
-
-
-
+
-
-
-
-







  return mask;
}

/*
** Expression pExpr is one operand of a comparison operator that might
** be useful for indexing.  This routine checks to see if pExpr appears
** in any index.  Return TRUE (1) if pExpr is an indexed term and return
** FALSE (0) if not.  If TRUE is returned, also set *piCur to the cursor
** number of the table that is indexed and *piColumn to the column number
** FALSE (0) if not.  If TRUE is returned, also set aiCurCol[0] to the cursor
** number of the table that is indexed and aiCurCol[1] to the column number
** of the column that is indexed, or XN_EXPR (-2) if an expression is being
** indexed.
**
** If pExpr is a TK_COLUMN column reference, then this routine always returns
** true even if that particular column is not indexed, because the column
** might be added to an automatic index later.
*/
static int exprMightBeIndexed(
static SQLITE_NOINLINE int exprMightBeIndexed2(
  SrcList *pFrom,        /* The FROM clause */
  int op,                /* The specific comparison operator */
  Bitmask mPrereq,       /* Bitmask of FROM clause terms referenced by pExpr */
  int *aiCurCol,         /* Write the referenced table cursor and column here */
  Expr *pExpr,           /* An operand of a comparison operator */
  Expr *pExpr            /* An operand of a comparison operator */
  int *piCur,            /* Write the referenced table cursor number here */
  int *piColumn          /* Write the referenced table column number here */
){
  Index *pIdx;
  int i;
  int iCur;
  for(i=0; mPrereq>1; i++, mPrereq>>=1){}
  iCur = pFrom->a[i].iCursor;
  for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    if( pIdx->aColExpr==0 ) continue;
    for(i=0; i<pIdx->nKeyCol; i++){
      if( pIdx->aiColumn[i]!=XN_EXPR ) continue;
      if( sqlite3ExprCompareSkip(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){
        aiCurCol[0] = iCur;
        aiCurCol[1] = XN_EXPR;
        return 1;

      }
    }
  }
  return 0;
}
static int exprMightBeIndexed(
  SrcList *pFrom,        /* The FROM clause */
  Bitmask mPrereq,       /* Bitmask of FROM clause terms referenced by pExpr */
  int *aiCurCol,         /* Write the referenced table cursor & column here */
  Expr *pExpr,           /* An operand of a comparison operator */
  int op                 /* The specific comparison operator */
){
  /* If this expression is a vector to the left or right of a 
  ** inequality constraint (>, <, >= or <=), perform the processing 
  ** on the first element of the vector.  */
  assert( TK_GT+1==TK_LE && TK_GT+2==TK_LT && TK_GT+3==TK_GE );
  assert( TK_IS<TK_GE && TK_ISNULL<TK_GE && TK_IN<TK_GE );
  assert( op<=TK_GE );
  if( pExpr->op==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){
    pExpr = pExpr->x.pList->a[0].pExpr;
  }

  if( pExpr->op==TK_COLUMN ){
    *piCur = pExpr->iTable;
    *piColumn = pExpr->iColumn;
    aiCurCol[0] = pExpr->iTable;
    aiCurCol[1] = pExpr->iColumn;
    return 1;
  }
  if( mPrereq==0 ) return 0;                 /* No table references */
  if( (mPrereq&(mPrereq-1))!=0 ) return 0;   /* Refs more than one table */
  for(i=0; mPrereq>1; i++, mPrereq>>=1){}
  iCur = pFrom->a[i].iCursor;
  for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    if( pIdx->aColExpr==0 ) continue;
    for(i=0; i<pIdx->nKeyCol; i++){
      if( pIdx->aiColumn[i]!=XN_EXPR ) continue;
      if( sqlite3ExprCompareSkip(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){
        *piCur = iCur;
        *piColumn = XN_EXPR;
        return 1;
  return exprMightBeIndexed2(pFrom,mPrereq,aiCurCol,pExpr);
      }
    }
  }
  return 0;
}

/*
** The input to this routine is an WhereTerm structure with only the
** "pExpr" field filled in.  The job of this routine is to analyze the
** subexpression and populate all the other fields of the WhereTerm
** structure.
957
958
959
960
961
962
963
964

965
966
967
968
969
970
971
972
973
974
975
976
977



978
979
980
981
982

983
984
985
986
987
988
989
963
964
965
966
967
968
969

970
971
972
973
974
975
976
977
978
979
980



981
982
983
984
985
986
987

988
989
990
991
992
993
994
995







-
+










-
-
-
+
+
+




-
+







    }
  }
  pTerm->prereqAll = prereqAll;
  pTerm->leftCursor = -1;
  pTerm->iParent = -1;
  pTerm->eOperator = 0;
  if( allowedOp(op) ){
    int iCur, iColumn;
    int aiCurCol[2];
    Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
    Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
    u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;

    if( pTerm->iField>0 ){
      assert( op==TK_IN );
      assert( pLeft->op==TK_VECTOR );
      pLeft = pLeft->x.pList->a[pTerm->iField-1].pExpr;
    }

    if( exprMightBeIndexed(pSrc, op, prereqLeft, pLeft, &iCur, &iColumn) ){
      pTerm->leftCursor = iCur;
      pTerm->u.leftColumn = iColumn;
    if( exprMightBeIndexed(pSrc, prereqLeft, aiCurCol, pLeft, op) ){
      pTerm->leftCursor = aiCurCol[0];
      pTerm->u.leftColumn = aiCurCol[1];
      pTerm->eOperator = operatorMask(op) & opMask;
    }
    if( op==TK_IS ) pTerm->wtFlags |= TERM_IS;
    if( pRight 
     && exprMightBeIndexed(pSrc, op, pTerm->prereqRight, pRight, &iCur,&iColumn)
     && exprMightBeIndexed(pSrc, pTerm->prereqRight, aiCurCol, pRight, op)
    ){
      WhereTerm *pNew;
      Expr *pDup;
      u16 eExtraOp = 0;        /* Extra bits for pNew->eOperator */
      assert( pTerm->iField==0 );
      if( pTerm->leftCursor>=0 ){
        int idxNew;
1005
1006
1007
1008
1009
1010
1011
1012
1013


1014
1015
1016
1017
1018
1019
1020
1011
1012
1013
1014
1015
1016
1017


1018
1019
1020
1021
1022
1023
1024
1025
1026







-
-
+
+







          eExtraOp = WO_EQUIV;
        }
      }else{
        pDup = pExpr;
        pNew = pTerm;
      }
      exprCommute(pParse, pDup);
      pNew->leftCursor = iCur;
      pNew->u.leftColumn = iColumn;
      pNew->leftCursor = aiCurCol[0];
      pNew->u.leftColumn = aiCurCol[1];
      testcase( (prereqLeft | extraRight) != prereqLeft );
      pNew->prereqRight = prereqLeft | extraRight;
      pNew->prereqAll = prereqAll;
      pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
    }
  }