engine/sqlite/src/where.cpp
author skip
Thu, 25 Feb 2010 14:29:19 +0000
changeset 2 29cda98b007e
permissions -rw-r--r--
Initial import of Podcatcher from the Bergamot project
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     1
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     2
** 2001 September 15
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     3
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     4
** The author disclaims copyright to this source code.  In place of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     5
** a legal notice, here is a blessing:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     6
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     7
**    May you do good and not evil.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     8
**    May you find forgiveness for yourself and forgive others.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     9
**    May you share freely, never taking more than you give.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    10
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    11
*************************************************************************
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    12
** This module contains C code that generates VDBE code used to process
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    13
** the WHERE clause of SQL statements.  This module is reponsible for
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    14
** generating the code that loops through a table looking for applicable
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    15
** rows.  Indices are selected and used to speed the search when doing
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    16
** so is applicable.  Because this module is responsible for selecting
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    17
** indices, you might also think of this module as the "query optimizer".
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    18
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    19
** $Id: where.cpp 1282 2008-11-13 09:31:33Z LarsPson $
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    20
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    21
#include "sqliteInt.h"
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    22
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    23
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    24
** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    25
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    26
#define BMS  (sizeof(Bitmask)*8)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    27
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    28
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    29
** Trace output macros
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    30
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    31
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    32
int sqlite3_where_trace = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    33
# define WHERETRACE(X)  if(sqlite3_where_trace) sqlite3DebugPrintf X
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    34
#else
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    35
# define WHERETRACE(X)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    36
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    37
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    38
/* Forward reference
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    39
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    40
typedef struct WhereClause WhereClause;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    41
typedef struct ExprMaskSet ExprMaskSet;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    42
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    43
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    44
** The query generator uses an array of instances of this structure to
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    45
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    46
** clause subexpression is separated from the others by an AND operator.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    47
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    48
** All WhereTerms are collected into a single WhereClause structure.  
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    49
** The following identity holds:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    50
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    51
**        WhereTerm.pWC->a[WhereTerm.idx] == WhereTerm
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    52
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    53
** When a term is of the form:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    54
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    55
**              X <op> <expr>
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    56
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    57
** where X is a column name and <op> is one of certain operators,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    58
** then WhereTerm.leftCursor and WhereTerm.leftColumn record the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    59
** cursor number and column number for X.  WhereTerm.operator records
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    60
** the <op> using a bitmask encoding defined by WO_xxx below.  The
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    61
** use of a bitmask encoding for the operator allows us to search
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    62
** quickly for terms that match any of several different operators.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    63
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    64
** prereqRight and prereqAll record sets of cursor numbers,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    65
** but they do so indirectly.  A single ExprMaskSet structure translates
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    66
** cursor number into bits and the translated bit is stored in the prereq
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    67
** fields.  The translation is used in order to maximize the number of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    68
** bits that will fit in a Bitmask.  The VDBE cursor numbers might be
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    69
** spread out over the non-negative integers.  For example, the cursor
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    70
** numbers might be 3, 8, 9, 10, 20, 23, 41, and 45.  The ExprMaskSet
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    71
** translates these sparse cursor numbers into consecutive integers
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    72
** beginning with 0 in order to make the best possible use of the available
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    73
** bits in the Bitmask.  So, in the example above, the cursor numbers
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    74
** would be mapped into integers 0 through 7.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    75
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    76
typedef struct WhereTerm WhereTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    77
struct WhereTerm {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    78
  Expr *pExpr;            /* Pointer to the subexpression */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    79
  i16 iParent;            /* Disable pWC->a[iParent] when this term disabled */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    80
  i16 leftCursor;         /* Cursor number of X in "X <op> <expr>" */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    81
  i16 leftColumn;         /* Column number of X in "X <op> <expr>" */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    82
  u16 eOperator;          /* A WO_xx value describing <op> */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    83
  u8 flags;               /* Bit flags.  See below */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    84
  u8 nChild;              /* Number of children that must disable us */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    85
  WhereClause *pWC;       /* The clause this term is part of */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    86
  Bitmask prereqRight;    /* Bitmask of tables used by pRight */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    87
  Bitmask prereqAll;      /* Bitmask of tables referenced by p */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    88
};
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    89
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    90
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    91
** Allowed values of WhereTerm.flags
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    92
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    93
#define TERM_DYNAMIC    0x01   /* Need to call sqlite3ExprDelete(pExpr) */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    94
#define TERM_VIRTUAL    0x02   /* Added by the optimizer.  Do not code */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    95
#define TERM_CODED      0x04   /* This term is already coded */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    96
#define TERM_COPIED     0x08   /* Has a child */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    97
#define TERM_OR_OK      0x10   /* Used during OR-clause processing */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    98
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    99
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   100
** An instance of the following structure holds all information about a
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   101
** WHERE clause.  Mostly this is a container for one or more WhereTerms.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   102
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   103
struct WhereClause {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   104
  Parse *pParse;           /* The parser context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   105
  ExprMaskSet *pMaskSet;   /* Mapping of table indices to bitmasks */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   106
  int nTerm;               /* Number of terms */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   107
  int nSlot;               /* Number of entries in a[] */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   108
  WhereTerm *a;            /* Each a[] describes a term of the WHERE cluase */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   109
  WhereTerm aStatic[10];   /* Initial static space for a[] */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   110
};
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   111
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   112
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   113
** An instance of the following structure keeps track of a mapping
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   114
** between VDBE cursor numbers and bits of the bitmasks in WhereTerm.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   115
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   116
** The VDBE cursor numbers are small integers contained in 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   117
** SrcList_item.iCursor and Expr.iTable fields.  For any given WHERE 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   118
** clause, the cursor numbers might not begin with 0 and they might
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   119
** contain gaps in the numbering sequence.  But we want to make maximum
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   120
** use of the bits in our bitmasks.  This structure provides a mapping
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   121
** from the sparse cursor numbers into consecutive integers beginning
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   122
** with 0.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   123
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   124
** If ExprMaskSet.ix[A]==B it means that The A-th bit of a Bitmask
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   125
** corresponds VDBE cursor number B.  The A-th bit of a bitmask is 1<<A.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   126
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   127
** For example, if the WHERE clause expression used these VDBE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   128
** cursors:  4, 5, 8, 29, 57, 73.  Then the  ExprMaskSet structure
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   129
** would map those cursor numbers into bits 0 through 5.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   130
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   131
** Note that the mapping is not necessarily ordered.  In the example
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   132
** above, the mapping might go like this:  4->3, 5->1, 8->2, 29->0,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   133
** 57->5, 73->4.  Or one of 719 other combinations might be used. It
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   134
** does not really matter.  What is important is that sparse cursor
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   135
** numbers all get mapped into bit numbers that begin with 0 and contain
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   136
** no gaps.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   137
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   138
struct ExprMaskSet {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   139
  int n;                        /* Number of assigned cursor values */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   140
  int ix[sizeof(Bitmask)*8];    /* Cursor assigned to each bit */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   141
};
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   142
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   143
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   144
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   145
** Bitmasks for the operators that indices are able to exploit.  An
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   146
** OR-ed combination of these values can be used when searching for
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   147
** terms in the where clause.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   148
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   149
#define WO_IN     1
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   150
#define WO_EQ     2
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   151
#define WO_LT     (WO_EQ<<(TK_LT-TK_EQ))
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   152
#define WO_LE     (WO_EQ<<(TK_LE-TK_EQ))
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   153
#define WO_GT     (WO_EQ<<(TK_GT-TK_EQ))
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   154
#define WO_GE     (WO_EQ<<(TK_GE-TK_EQ))
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   155
#define WO_MATCH  64
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   156
#define WO_ISNULL 128
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   157
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   158
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   159
** Value for flags returned by bestIndex().  
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   160
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   161
** The least significant byte is reserved as a mask for WO_ values above.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   162
** The WhereLevel.flags field is usually set to WO_IN|WO_EQ|WO_ISNULL.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   163
** But if the table is the right table of a left join, WhereLevel.flags
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   164
** is set to WO_IN|WO_EQ.  The WhereLevel.flags field can then be used as
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   165
** the "op" parameter to findTerm when we are resolving equality constraints.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   166
** ISNULL constraints will then not be used on the right table of a left
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   167
** join.  Tickets #2177 and #2189.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   168
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   169
#define WHERE_ROWID_EQ     0x000100   /* rowid=EXPR or rowid IN (...) */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   170
#define WHERE_ROWID_RANGE  0x000200   /* rowid<EXPR and/or rowid>EXPR */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   171
#define WHERE_COLUMN_EQ    0x001000   /* x=EXPR or x IN (...) */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   172
#define WHERE_COLUMN_RANGE 0x002000   /* x<EXPR and/or x>EXPR */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   173
#define WHERE_COLUMN_IN    0x004000   /* x IN (...) */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   174
#define WHERE_TOP_LIMIT    0x010000   /* x<EXPR or x<=EXPR constraint */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   175
#define WHERE_BTM_LIMIT    0x020000   /* x>EXPR or x>=EXPR constraint */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   176
#define WHERE_IDX_ONLY     0x080000   /* Use index only - omit table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   177
#define WHERE_ORDERBY      0x100000   /* Output will appear in correct order */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   178
#define WHERE_REVERSE      0x200000   /* Scan in reverse order */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   179
#define WHERE_UNIQUE       0x400000   /* Selects no more than one row */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   180
#define WHERE_VIRTUALTABLE 0x800000   /* Use virtual-table processing */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   181
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   182
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   183
** Initialize a preallocated WhereClause structure.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   184
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   185
static void whereClauseInit(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   186
  WhereClause *pWC,        /* The WhereClause to be initialized */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   187
  Parse *pParse,           /* The parsing context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   188
  ExprMaskSet *pMaskSet    /* Mapping from table indices to bitmasks */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   189
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   190
  pWC->pParse = pParse;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   191
  pWC->pMaskSet = pMaskSet;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   192
  pWC->nTerm = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   193
  pWC->nSlot = ArraySize(pWC->aStatic);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   194
  pWC->a = pWC->aStatic;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   195
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   196
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   197
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   198
** Deallocate a WhereClause structure.  The WhereClause structure
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   199
** itself is not freed.  This routine is the inverse of whereClauseInit().
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   200
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   201
static void whereClauseClear(WhereClause *pWC){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   202
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   203
  WhereTerm *a;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   204
  for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   205
    if( a->flags & TERM_DYNAMIC ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   206
      sqlite3ExprDelete(a->pExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   207
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   208
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   209
  if( pWC->a!=pWC->aStatic ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   210
    sqlite3_free(pWC->a);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   211
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   212
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   213
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   214
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   215
** Add a new entries to the WhereClause structure.  Increase the allocated
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   216
** space as necessary.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   217
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   218
** If the flags argument includes TERM_DYNAMIC, then responsibility
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   219
** for freeing the expression p is assumed by the WhereClause object.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   220
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   221
** WARNING:  This routine might reallocate the space used to store
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   222
** WhereTerms.  All pointers to WhereTerms should be invalided after
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   223
** calling this routine.  Such pointers may be reinitialized by referencing
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   224
** the pWC->a[] array.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   225
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   226
static int whereClauseInsert(WhereClause *pWC, Expr *p, int flags){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   227
  WhereTerm *pTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   228
  int idx;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   229
  if( pWC->nTerm>=pWC->nSlot ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   230
    WhereTerm *pOld = pWC->a;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   231
    pWC->a = (WhereTerm*)sqlite3_malloc( sizeof(pWC->a[0])*pWC->nSlot*2 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   232
    if( pWC->a==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   233
      pWC->pParse->db->mallocFailed = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   234
      if( flags & TERM_DYNAMIC ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   235
        sqlite3ExprDelete(p);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   236
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   237
      pWC->a = pOld;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   238
      return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   239
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   240
    memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   241
    if( pOld!=pWC->aStatic ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   242
      sqlite3_free(pOld);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   243
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   244
    pWC->nSlot *= 2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   245
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   246
  pTerm = &pWC->a[idx = pWC->nTerm];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   247
  pWC->nTerm++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   248
  pTerm->pExpr = p;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   249
  pTerm->flags = flags;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   250
  pTerm->pWC = pWC;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   251
  pTerm->iParent = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   252
  return idx;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   253
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   254
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   255
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   256
** This routine identifies subexpressions in the WHERE clause where
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   257
** each subexpression is separated by the AND operator or some other
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   258
** operator specified in the op parameter.  The WhereClause structure
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   259
** is filled with pointers to subexpressions.  For example:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   260
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   261
**    WHERE  a=='hello' AND coalesce(b,11)<10 AND (c+12!=d OR c==22)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   262
**           \________/     \_______________/     \________________/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   263
**            slot[0]            slot[1]               slot[2]
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   264
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   265
** The original WHERE clause in pExpr is unaltered.  All this routine
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   266
** does is make slot[] entries point to substructure within pExpr.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   267
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   268
** In the previous sentence and in the diagram, "slot[]" refers to
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   269
** the WhereClause.a[] array.  This array grows as needed to contain
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   270
** all terms of the WHERE clause.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   271
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   272
static void whereSplit(WhereClause *pWC, Expr *pExpr, int op){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   273
  if( pExpr==0 ) return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   274
  if( pExpr->op!=op ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   275
    whereClauseInsert(pWC, pExpr, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   276
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   277
    whereSplit(pWC, pExpr->pLeft, op);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   278
    whereSplit(pWC, pExpr->pRight, op);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   279
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   280
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   281
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   282
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   283
** Initialize an expression mask set
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   284
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   285
#define initMaskSet(P)  memset(P, 0, sizeof(*P))
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   286
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   287
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   288
** Return the bitmask for the given cursor number.  Return 0 if
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   289
** iCursor is not in the set.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   290
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   291
static Bitmask getMask(ExprMaskSet *pMaskSet, int iCursor){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   292
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   293
  for(i=0; i<pMaskSet->n; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   294
    if( pMaskSet->ix[i]==iCursor ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   295
      return ((Bitmask)1)<<i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   296
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   297
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   298
  return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   299
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   300
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   301
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   302
** Create a new mask for cursor iCursor.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   303
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   304
** There is one cursor per table in the FROM clause.  The number of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   305
** tables in the FROM clause is limited by a test early in the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   306
** sqlite3WhereBegin() routine.  So we know that the pMaskSet->ix[]
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   307
** array will never overflow.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   308
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   309
static void createMask(ExprMaskSet *pMaskSet, int iCursor){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   310
  assert( pMaskSet->n < ArraySize(pMaskSet->ix) );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   311
  pMaskSet->ix[pMaskSet->n++] = iCursor;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   312
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   313
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   314
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   315
** This routine walks (recursively) an expression tree and generates
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   316
** a bitmask indicating which tables are used in that expression
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   317
** tree.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   318
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   319
** In order for this routine to work, the calling function must have
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   320
** previously invoked sqlite3ExprResolveNames() on the expression.  See
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   321
** the header comment on that routine for additional information.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   322
** The sqlite3ExprResolveNames() routines looks for column names and
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   323
** sets their opcodes to TK_COLUMN and their Expr.iTable fields to
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   324
** the VDBE cursor number of the table.  This routine just has to
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   325
** translate the cursor numbers into bitmask values and OR all
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   326
** the bitmasks together.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   327
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   328
static Bitmask exprListTableUsage(ExprMaskSet*, ExprList*);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   329
static Bitmask exprSelectTableUsage(ExprMaskSet*, Select*);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   330
static Bitmask exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   331
  Bitmask mask = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   332
  if( p==0 ) return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   333
  if( p->op==TK_COLUMN ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   334
    mask = getMask(pMaskSet, p->iTable);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   335
    return mask;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   336
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   337
  mask = exprTableUsage(pMaskSet, p->pRight);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   338
  mask |= exprTableUsage(pMaskSet, p->pLeft);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   339
  mask |= exprListTableUsage(pMaskSet, p->pList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   340
  mask |= exprSelectTableUsage(pMaskSet, p->pSelect);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   341
  return mask;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   342
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   343
static Bitmask exprListTableUsage(ExprMaskSet *pMaskSet, ExprList *pList){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   344
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   345
  Bitmask mask = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   346
  if( pList ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   347
    for(i=0; i<pList->nExpr; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   348
      mask |= exprTableUsage(pMaskSet, pList->a[i].pExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   349
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   350
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   351
  return mask;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   352
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   353
static Bitmask exprSelectTableUsage(ExprMaskSet *pMaskSet, Select *pS){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   354
  Bitmask mask = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   355
  while( pS ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   356
    mask |= exprListTableUsage(pMaskSet, pS->pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   357
    mask |= exprListTableUsage(pMaskSet, pS->pGroupBy);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   358
    mask |= exprListTableUsage(pMaskSet, pS->pOrderBy);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   359
    mask |= exprTableUsage(pMaskSet, pS->pWhere);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   360
    mask |= exprTableUsage(pMaskSet, pS->pHaving);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   361
    pS = pS->pPrior;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   362
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   363
  return mask;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   364
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   365
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   366
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   367
** Return TRUE if the given operator is one of the operators that is
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   368
** allowed for an indexable WHERE clause term.  The allowed operators are
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   369
** "=", "<", ">", "<=", ">=", and "IN".
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   370
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   371
static int allowedOp(int op){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   372
  assert( TK_GT>TK_EQ && TK_GT<TK_GE );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   373
  assert( TK_LT>TK_EQ && TK_LT<TK_GE );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   374
  assert( TK_LE>TK_EQ && TK_LE<TK_GE );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   375
  assert( TK_GE==TK_EQ+4 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   376
  return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   377
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   378
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   379
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   380
** Swap two objects of type T.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   381
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   382
#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   383
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   384
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   385
** Commute a comparision operator.  Expressions of the form "X op Y"
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   386
** are converted into "Y op X".
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   387
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   388
** If a collation sequence is associated with either the left or right
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   389
** side of the comparison, it remains associated with the same side after
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   390
** the commutation. So "Y collate NOCASE op X" becomes 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   391
** "X collate NOCASE op Y". This is because any collation sequence on
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   392
** the left hand side of a comparison overrides any collation sequence 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   393
** attached to the right. For the same reason the EP_ExpCollate flag
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   394
** is not commuted.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   395
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   396
static void exprCommute(Expr *pExpr){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   397
  u16 expRight = (pExpr->pRight->flags & EP_ExpCollate);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   398
  u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   399
  assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   400
  SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   401
  pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   402
  pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   403
  SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   404
  if( pExpr->op>=TK_GT ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   405
    assert( TK_LT==TK_GT+2 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   406
    assert( TK_GE==TK_LE+2 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   407
    assert( TK_GT>TK_EQ );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   408
    assert( TK_GT<TK_LE );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   409
    assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   410
    pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   411
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   412
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   413
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   414
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   415
** Translate from TK_xx operator to WO_xx bitmask.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   416
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   417
static int operatorMask(int op){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   418
  int c;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   419
  assert( allowedOp(op) );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   420
  if( op==TK_IN ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   421
    c = WO_IN;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   422
  }else if( op==TK_ISNULL ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   423
    c = WO_ISNULL;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   424
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   425
    c = WO_EQ<<(op-TK_EQ);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   426
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   427
  assert( op!=TK_ISNULL || c==WO_ISNULL );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   428
  assert( op!=TK_IN || c==WO_IN );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   429
  assert( op!=TK_EQ || c==WO_EQ );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   430
  assert( op!=TK_LT || c==WO_LT );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   431
  assert( op!=TK_LE || c==WO_LE );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   432
  assert( op!=TK_GT || c==WO_GT );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   433
  assert( op!=TK_GE || c==WO_GE );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   434
  return c;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   435
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   436
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   437
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   438
** Search for a term in the WHERE clause that is of the form "X <op> <expr>"
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   439
** where X is a reference to the iColumn of table iCur and <op> is one of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   440
** the WO_xx operator codes specified by the op parameter.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   441
** Return a pointer to the term.  Return 0 if not found.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   442
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   443
static WhereTerm *findTerm(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   444
  WhereClause *pWC,     /* The WHERE clause to be searched */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   445
  int iCur,             /* Cursor number of LHS */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   446
  int iColumn,          /* Column number of LHS */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   447
  Bitmask notReady,     /* RHS must not overlap with this mask */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   448
  u16 op,               /* Mask of WO_xx values describing operator */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   449
  Index *pIdx           /* Must be compatible with this index, if not NULL */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   450
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   451
  WhereTerm *pTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   452
  int k;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   453
  for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   454
    if( pTerm->leftCursor==iCur
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   455
       && (pTerm->prereqRight & notReady)==0
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   456
       && pTerm->leftColumn==iColumn
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   457
       && (pTerm->eOperator & op)!=0
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   458
    ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   459
      if( iCur>=0 && pIdx && pTerm->eOperator!=WO_ISNULL ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   460
        Expr *pX = pTerm->pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   461
        CollSeq *pColl;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   462
        char idxaff;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   463
        int j;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   464
        Parse *pParse = pWC->pParse;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   465
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   466
        idxaff = pIdx->pTable->aCol[iColumn].affinity;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   467
        if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   468
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   469
        /* Figure out the collation sequence required from an index for
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   470
        ** it to be useful for optimising expression pX. Store this
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   471
        ** value in variable pColl.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   472
        */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   473
        assert(pX->pLeft);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   474
        pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   475
        if( !pColl ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   476
          pColl = pParse->db->pDfltColl;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   477
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   478
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   479
        for(j=0; j<pIdx->nColumn && pIdx->aiColumn[j]!=iColumn; j++){}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   480
        assert( j<pIdx->nColumn );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   481
        if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   482
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   483
      return pTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   484
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   485
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   486
  return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   487
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   488
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   489
/* Forward reference */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   490
static void exprAnalyze(SrcList*, WhereClause*, int);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   491
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   492
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   493
** Call exprAnalyze on all terms in a WHERE clause.  
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   494
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   495
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   496
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   497
static void exprAnalyzeAll(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   498
  SrcList *pTabList,       /* the FROM clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   499
  WhereClause *pWC         /* the WHERE clause to be analyzed */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   500
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   501
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   502
  for(i=pWC->nTerm-1; i>=0; i--){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   503
    exprAnalyze(pTabList, pWC, i);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   504
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   505
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   506
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   507
#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   508
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   509
** Check to see if the given expression is a LIKE or GLOB operator that
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   510
** can be optimized using inequality constraints.  Return TRUE if it is
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   511
** so and false if not.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   512
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   513
** In order for the operator to be optimizible, the RHS must be a string
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   514
** literal that does not begin with a wildcard.  
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   515
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   516
static int isLikeOrGlob(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   517
  sqlite3 *db,      /* The database */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   518
  Expr *pExpr,      /* Test this expression */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   519
  int *pnPattern,   /* Number of non-wildcard prefix characters */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   520
  int *pisComplete  /* True if the only wildcard is % in the last character */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   521
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   522
  const char *z;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   523
  Expr *pRight, *pLeft;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   524
  ExprList *pList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   525
  int c, cnt;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   526
  int noCase;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   527
  char wc[3];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   528
  CollSeq *pColl;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   529
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   530
  if( !sqlite3IsLikeFunction(db, pExpr, &noCase, wc) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   531
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   532
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   533
  pList = pExpr->pList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   534
  pRight = pList->a[0].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   535
  if( pRight->op!=TK_STRING ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   536
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   537
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   538
  pLeft = pList->a[1].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   539
  if( pLeft->op!=TK_COLUMN ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   540
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   541
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   542
  pColl = pLeft->pColl;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   543
  if( pColl==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   544
    /* TODO: Coverage testing doesn't get this case. Is it actually possible
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   545
    ** for an expression of type TK_COLUMN to not have an assigned collation 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   546
    ** sequence at this point?
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   547
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   548
    pColl = db->pDfltColl;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   549
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   550
  if( (pColl->type!=SQLITE_COLL_BINARY || noCase) &&
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   551
      (pColl->type!=SQLITE_COLL_NOCASE || !noCase) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   552
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   553
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   554
  sqlite3DequoteExpr(db, pRight);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   555
  z = (char *)pRight->token.z;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   556
  cnt = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   557
  if( z ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   558
    while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ cnt++; }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   559
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   560
  if( cnt==0 || 255==(u8)z[cnt] ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   561
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   562
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   563
  *pisComplete = z[cnt]==wc[0] && z[cnt+1]==0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   564
  *pnPattern = cnt;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   565
  return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   566
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   567
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   568
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   569
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   570
#ifndef SQLITE_OMIT_VIRTUALTABLE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   571
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   572
** Check to see if the given expression is of the form
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   573
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   574
**         column MATCH expr
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   575
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   576
** If it is then return TRUE.  If not, return FALSE.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   577
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   578
static int isMatchOfColumn(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   579
  Expr *pExpr      /* Test this expression */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   580
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   581
  ExprList *pList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   582
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   583
  if( pExpr->op!=TK_FUNCTION ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   584
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   585
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   586
  if( pExpr->token.n!=5 ||
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   587
       sqlite3StrNICmp((const char*)pExpr->token.z,"match",5)!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   588
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   589
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   590
  pList = pExpr->pList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   591
  if( pList->nExpr!=2 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   592
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   593
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   594
  if( pList->a[1].pExpr->op != TK_COLUMN ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   595
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   596
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   597
  return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   598
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   599
#endif /* SQLITE_OMIT_VIRTUALTABLE */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   600
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   601
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   602
** If the pBase expression originated in the ON or USING clause of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   603
** a join, then transfer the appropriate markings over to derived.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   604
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   605
static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   606
  pDerived->flags |= pBase->flags & EP_FromJoin;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   607
  pDerived->iRightJoinTable = pBase->iRightJoinTable;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   608
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   609
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   610
#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   611
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   612
** Return TRUE if the given term of an OR clause can be converted
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   613
** into an IN clause.  The iCursor and iColumn define the left-hand
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   614
** side of the IN clause.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   615
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   616
** The context is that we have multiple OR-connected equality terms
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   617
** like this:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   618
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   619
**           a=<expr1> OR  a=<expr2> OR b=<expr3>  OR ...
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   620
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   621
** The pOrTerm input to this routine corresponds to a single term of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   622
** this OR clause.  In order for the term to be a condidate for
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   623
** conversion to an IN operator, the following must be true:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   624
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   625
**     *  The left-hand side of the term must be the column which
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   626
**        is identified by iCursor and iColumn.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   627
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   628
**     *  If the right-hand side is also a column, then the affinities
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   629
**        of both right and left sides must be such that no type
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   630
**        conversions are required on the right.  (Ticket #2249)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   631
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   632
** If both of these conditions are true, then return true.  Otherwise
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   633
** return false.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   634
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   635
static int orTermIsOptCandidate(WhereTerm *pOrTerm, int iCursor, int iColumn){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   636
  int affLeft, affRight;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   637
  assert( pOrTerm->eOperator==WO_EQ );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   638
  if( pOrTerm->leftCursor!=iCursor ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   639
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   640
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   641
  if( pOrTerm->leftColumn!=iColumn ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   642
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   643
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   644
  affRight = sqlite3ExprAffinity(pOrTerm->pExpr->pRight);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   645
  if( affRight==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   646
    return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   647
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   648
  affLeft = sqlite3ExprAffinity(pOrTerm->pExpr->pLeft);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   649
  if( affRight!=affLeft ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   650
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   651
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   652
  return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   653
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   654
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   655
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   656
** Return true if the given term of an OR clause can be ignored during
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   657
** a check to make sure all OR terms are candidates for optimization.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   658
** In other words, return true if a call to the orTermIsOptCandidate()
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   659
** above returned false but it is not necessary to disqualify the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   660
** optimization.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   661
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   662
** Suppose the original OR phrase was this:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   663
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   664
**           a=4  OR  a=11  OR  a=b
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   665
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   666
** During analysis, the third term gets flipped around and duplicate
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   667
** so that we are left with this:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   668
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   669
**           a=4  OR  a=11  OR  a=b  OR  b=a
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   670
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   671
** Since the last two terms are duplicates, only one of them
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   672
** has to qualify in order for the whole phrase to qualify.  When
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   673
** this routine is called, we know that pOrTerm did not qualify.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   674
** This routine merely checks to see if pOrTerm has a duplicate that
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   675
** might qualify.  If there is a duplicate that has not yet been
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   676
** disqualified, then return true.  If there are no duplicates, or
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   677
** the duplicate has also been disqualifed, return false.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   678
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   679
static int orTermHasOkDuplicate(WhereClause *pOr, WhereTerm *pOrTerm){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   680
  if( pOrTerm->flags & TERM_COPIED ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   681
    /* This is the original term.  The duplicate is to the left had
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   682
    ** has not yet been analyzed and thus has not yet been disqualified. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   683
    return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   684
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   685
  if( (pOrTerm->flags & TERM_VIRTUAL)!=0
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   686
     && (pOr->a[pOrTerm->iParent].flags & TERM_OR_OK)!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   687
    /* This is a duplicate term.  The original qualified so this one
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   688
    ** does not have to. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   689
    return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   690
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   691
  /* This is either a singleton term or else it is a duplicate for
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   692
  ** which the original did not qualify.  Either way we are done for. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   693
  return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   694
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   695
#endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   696
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   697
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   698
** The input to this routine is an WhereTerm structure with only the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   699
** "pExpr" field filled in.  The job of this routine is to analyze the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   700
** subexpression and populate all the other fields of the WhereTerm
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   701
** structure.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   702
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   703
** If the expression is of the form "<expr> <op> X" it gets commuted
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   704
** to the standard form of "X <op> <expr>".  If the expression is of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   705
** the form "X <op> Y" where both X and Y are columns, then the original
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   706
** expression is unchanged and a new virtual expression of the form
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   707
** "Y <op> X" is added to the WHERE clause and analyzed separately.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   708
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   709
static void exprAnalyze(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   710
  SrcList *pSrc,            /* the FROM clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   711
  WhereClause *pWC,         /* the WHERE clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   712
  int idxTerm               /* Index of the term to be analyzed */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   713
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   714
  WhereTerm *pTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   715
  ExprMaskSet *pMaskSet;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   716
  Expr *pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   717
  Bitmask prereqLeft;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   718
  Bitmask prereqAll;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   719
  int nPattern;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   720
  int isComplete;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   721
  int op;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   722
  Parse *pParse = pWC->pParse;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   723
  sqlite3 *db = pParse->db;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   724
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   725
  if( db->mallocFailed ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   726
    return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   727
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   728
  pTerm = &pWC->a[idxTerm];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   729
  pMaskSet = pWC->pMaskSet;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   730
  pExpr = pTerm->pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   731
  prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   732
  op = pExpr->op;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   733
  if( op==TK_IN ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   734
    assert( pExpr->pRight==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   735
    pTerm->prereqRight = exprListTableUsage(pMaskSet, pExpr->pList)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   736
                          | exprSelectTableUsage(pMaskSet, pExpr->pSelect);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   737
  }else if( op==TK_ISNULL ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   738
    pTerm->prereqRight = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   739
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   740
    pTerm->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   741
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   742
  prereqAll = exprTableUsage(pMaskSet, pExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   743
  if( ExprHasProperty(pExpr, EP_FromJoin) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   744
    prereqAll |= getMask(pMaskSet, pExpr->iRightJoinTable);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   745
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   746
  pTerm->prereqAll = prereqAll;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   747
  pTerm->leftCursor = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   748
  pTerm->iParent = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   749
  pTerm->eOperator = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   750
  if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   751
    Expr *pLeft = pExpr->pLeft;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   752
    Expr *pRight = pExpr->pRight;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   753
    if( pLeft->op==TK_COLUMN ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   754
      pTerm->leftCursor = pLeft->iTable;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   755
      pTerm->leftColumn = pLeft->iColumn;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   756
      pTerm->eOperator = operatorMask(op);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   757
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   758
    if( pRight && pRight->op==TK_COLUMN ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   759
      WhereTerm *pNew;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   760
      Expr *pDup;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   761
      if( pTerm->leftCursor>=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   762
        int idxNew;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   763
        pDup = sqlite3ExprDup(db, pExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   764
        if( db->mallocFailed ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   765
          sqlite3ExprDelete(pDup);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   766
          return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   767
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   768
        idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   769
        if( idxNew==0 ) return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   770
        pNew = &pWC->a[idxNew];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   771
        pNew->iParent = idxTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   772
        pTerm = &pWC->a[idxTerm];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   773
        pTerm->nChild = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   774
        pTerm->flags |= TERM_COPIED;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   775
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   776
        pDup = pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   777
        pNew = pTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   778
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   779
      exprCommute(pDup);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   780
      pLeft = pDup->pLeft;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   781
      pNew->leftCursor = pLeft->iTable;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   782
      pNew->leftColumn = pLeft->iColumn;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   783
      pNew->prereqRight = prereqLeft;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   784
      pNew->prereqAll = prereqAll;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   785
      pNew->eOperator = operatorMask(pDup->op);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   786
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   787
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   788
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   789
#ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   790
  /* If a term is the BETWEEN operator, create two new virtual terms
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   791
  ** that define the range that the BETWEEN implements.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   792
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   793
  else if( pExpr->op==TK_BETWEEN ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   794
    ExprList *pList = pExpr->pList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   795
    int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   796
    static const u8 ops[] = {TK_GE, TK_LE};
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   797
    assert( pList!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   798
    assert( pList->nExpr==2 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   799
    for(i=0; i<2; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   800
      Expr *pNewExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   801
      int idxNew;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   802
      pNewExpr = sqlite3Expr(db, ops[i], sqlite3ExprDup(db, pExpr->pLeft),
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   803
                             sqlite3ExprDup(db, pList->a[i].pExpr), 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   804
      idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   805
      exprAnalyze(pSrc, pWC, idxNew);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   806
      pTerm = &pWC->a[idxTerm];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   807
      pWC->a[idxNew].iParent = idxTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   808
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   809
    pTerm->nChild = 2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   810
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   811
#endif /* SQLITE_OMIT_BETWEEN_OPTIMIZATION */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   812
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   813
#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   814
  /* Attempt to convert OR-connected terms into an IN operator so that
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   815
  ** they can make use of indices.  Example:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   816
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   817
  **      x = expr1  OR  expr2 = x  OR  x = expr3
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   818
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   819
  ** is converted into
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   820
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   821
  **      x IN (expr1,expr2,expr3)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   822
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   823
  ** This optimization must be omitted if OMIT_SUBQUERY is defined because
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   824
  ** the compiler for the the IN operator is part of sub-queries.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   825
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   826
  else if( pExpr->op==TK_OR ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   827
    int ok;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   828
    int i, j;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   829
    int iColumn, iCursor;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   830
    WhereClause sOr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   831
    WhereTerm *pOrTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   832
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   833
    assert( (pTerm->flags & TERM_DYNAMIC)==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   834
    whereClauseInit(&sOr, pWC->pParse, pMaskSet);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   835
    whereSplit(&sOr, pExpr, TK_OR);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   836
    exprAnalyzeAll(pSrc, &sOr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   837
    assert( sOr.nTerm>=2 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   838
    j = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   839
    do{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   840
      assert( j<sOr.nTerm );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   841
      iColumn = sOr.a[j].leftColumn;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   842
      iCursor = sOr.a[j].leftCursor;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   843
      ok = iCursor>=0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   844
      for(i=sOr.nTerm-1, pOrTerm=sOr.a; i>=0 && ok; i--, pOrTerm++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   845
        if( pOrTerm->eOperator!=WO_EQ ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   846
          goto or_not_possible;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   847
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   848
        if( orTermIsOptCandidate(pOrTerm, iCursor, iColumn) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   849
          pOrTerm->flags |= TERM_OR_OK;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   850
        }else if( orTermHasOkDuplicate(&sOr, pOrTerm) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   851
          pOrTerm->flags &= ~TERM_OR_OK;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   852
        }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   853
          ok = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   854
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   855
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   856
    }while( !ok && (sOr.a[j++].flags & TERM_COPIED)!=0 && j<2 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   857
    if( ok ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   858
      ExprList *pList = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   859
      Expr *pNew, *pDup;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   860
      Expr *pLeft = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   861
      for(i=sOr.nTerm-1, pOrTerm=sOr.a; i>=0 && ok; i--, pOrTerm++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   862
        if( (pOrTerm->flags & TERM_OR_OK)==0 ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   863
        pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   864
        pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   865
        pLeft = pOrTerm->pExpr->pLeft;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   866
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   867
      assert( pLeft!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   868
      pDup = sqlite3ExprDup(db, pLeft);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   869
      pNew = sqlite3Expr(db, TK_IN, pDup, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   870
      if( pNew ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   871
        int idxNew;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   872
        transferJoinMarkings(pNew, pExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   873
        pNew->pList = pList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   874
        idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   875
        exprAnalyze(pSrc, pWC, idxNew);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   876
        pTerm = &pWC->a[idxTerm];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   877
        pWC->a[idxNew].iParent = idxTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   878
        pTerm->nChild = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   879
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   880
        sqlite3ExprListDelete(pList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   881
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   882
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   883
or_not_possible:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   884
    whereClauseClear(&sOr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   885
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   886
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   887
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   888
#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   889
  /* Add constraints to reduce the search space on a LIKE or GLOB
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   890
  ** operator.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   891
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   892
  if( isLikeOrGlob(db, pExpr, &nPattern, &isComplete) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   893
    Expr *pLeft, *pRight;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   894
    Expr *pStr1, *pStr2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   895
    Expr *pNewExpr1, *pNewExpr2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   896
    int idxNew1, idxNew2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   897
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   898
    pLeft = pExpr->pList->a[1].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   899
    pRight = pExpr->pList->a[0].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   900
    pStr1 = sqlite3PExpr(pParse, TK_STRING, 0, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   901
    if( pStr1 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   902
      sqlite3TokenCopy(db, &pStr1->token, &pRight->token);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   903
      pStr1->token.n = nPattern;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   904
      pStr1->flags = EP_Dequoted;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   905
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   906
    pStr2 = sqlite3ExprDup(db, pStr1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   907
    if( !db->mallocFailed ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   908
      assert( pStr2->token.dyn );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   909
      ++*(u8*)&pStr2->token.z[nPattern-1];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   910
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   911
    pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprDup(db,pLeft), pStr1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   912
    idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   913
    exprAnalyze(pSrc, pWC, idxNew1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   914
    pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprDup(db,pLeft), pStr2, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   915
    idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   916
    exprAnalyze(pSrc, pWC, idxNew2);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   917
    pTerm = &pWC->a[idxTerm];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   918
    if( isComplete ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   919
      pWC->a[idxNew1].iParent = idxTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   920
      pWC->a[idxNew2].iParent = idxTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   921
      pTerm->nChild = 2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   922
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   923
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   924
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   925
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   926
#ifndef SQLITE_OMIT_VIRTUALTABLE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   927
  /* Add a WO_MATCH auxiliary term to the constraint set if the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   928
  ** current expression is of the form:  column MATCH expr.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   929
  ** This information is used by the xBestIndex methods of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   930
  ** virtual tables.  The native query optimizer does not attempt
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   931
  ** to do anything with MATCH functions.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   932
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   933
  if( isMatchOfColumn(pExpr) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   934
    int idxNew;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   935
    Expr *pRight, *pLeft;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   936
    WhereTerm *pNewTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   937
    Bitmask prereqColumn, prereqExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   938
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   939
    pRight = pExpr->pList->a[0].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   940
    pLeft = pExpr->pList->a[1].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   941
    prereqExpr = exprTableUsage(pMaskSet, pRight);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   942
    prereqColumn = exprTableUsage(pMaskSet, pLeft);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   943
    if( (prereqExpr & prereqColumn)==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   944
      Expr *pNewExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   945
      pNewExpr = sqlite3Expr(db, TK_MATCH, 0, sqlite3ExprDup(db, pRight), 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   946
      idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   947
      pNewTerm = &pWC->a[idxNew];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   948
      pNewTerm->prereqRight = prereqExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   949
      pNewTerm->leftCursor = pLeft->iTable;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   950
      pNewTerm->leftColumn = pLeft->iColumn;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   951
      pNewTerm->eOperator = WO_MATCH;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   952
      pNewTerm->iParent = idxTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   953
      pTerm = &pWC->a[idxTerm];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   954
      pTerm->nChild = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   955
      pTerm->flags |= TERM_COPIED;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   956
      pNewTerm->prereqAll = pTerm->prereqAll;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   957
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   958
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   959
#endif /* SQLITE_OMIT_VIRTUALTABLE */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   960
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   961
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   962
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   963
** Return TRUE if any of the expressions in pList->a[iFirst...] contain
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   964
** a reference to any table other than the iBase table.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   965
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   966
static int referencesOtherTables(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   967
  ExprList *pList,          /* Search expressions in ths list */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   968
  ExprMaskSet *pMaskSet,    /* Mapping from tables to bitmaps */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   969
  int iFirst,               /* Be searching with the iFirst-th expression */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   970
  int iBase                 /* Ignore references to this table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   971
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   972
  Bitmask allowed = ~getMask(pMaskSet, iBase);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   973
  while( iFirst<pList->nExpr ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   974
    if( (exprTableUsage(pMaskSet, pList->a[iFirst++].pExpr)&allowed)!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   975
      return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   976
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   977
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   978
  return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   979
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   980
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   981
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   982
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   983
** This routine decides if pIdx can be used to satisfy the ORDER BY
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   984
** clause.  If it can, it returns 1.  If pIdx cannot satisfy the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   985
** ORDER BY clause, this routine returns 0.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   986
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   987
** pOrderBy is an ORDER BY clause from a SELECT statement.  pTab is the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   988
** left-most table in the FROM clause of that same SELECT statement and
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   989
** the table has a cursor number of "base".  pIdx is an index on pTab.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   990
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   991
** nEqCol is the number of columns of pIdx that are used as equality
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   992
** constraints.  Any of these columns may be missing from the ORDER BY
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   993
** clause and the match can still be a success.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   994
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   995
** All terms of the ORDER BY that match against the index must be either
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   996
** ASC or DESC.  (Terms of the ORDER BY clause past the end of a UNIQUE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   997
** index do not need to satisfy this constraint.)  The *pbRev value is
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   998
** set to 1 if the ORDER BY clause is all DESC and it is set to 0 if
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   999
** the ORDER BY clause is all ASC.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1000
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1001
static int isSortingIndex(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1002
  Parse *pParse,          /* Parsing context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1003
  ExprMaskSet *pMaskSet,  /* Mapping from table indices to bitmaps */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1004
  Index *pIdx,            /* The index we are testing */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1005
  int base,               /* Cursor number for the table to be sorted */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1006
  ExprList *pOrderBy,     /* The ORDER BY clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1007
  int nEqCol,             /* Number of index columns with == constraints */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1008
  int *pbRev              /* Set to 1 if ORDER BY is DESC */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1009
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1010
  int i, j;                       /* Loop counters */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1011
  int sortOrder = 0;              /* XOR of index and ORDER BY sort direction */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1012
  int nTerm;                      /* Number of ORDER BY terms */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1013
  ExprList::ExprList_item *pTerm;    /* A term of the ORDER BY clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1014
  sqlite3 *db = pParse->db;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1015
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1016
  assert( pOrderBy!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1017
  nTerm = pOrderBy->nExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1018
  assert( nTerm>0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1019
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1020
  /* Match terms of the ORDER BY clause against columns of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1021
  ** the index.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1022
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1023
  ** Note that indices have pIdx->nColumn regular columns plus
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1024
  ** one additional column containing the rowid.  The rowid column
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1025
  ** of the index is also allowed to match against the ORDER BY
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1026
  ** clause.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1027
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1028
  for(i=j=0, pTerm=pOrderBy->a; j<nTerm && i<=pIdx->nColumn; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1029
    Expr *pExpr;       /* The expression of the ORDER BY pTerm */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1030
    CollSeq *pColl;    /* The collating sequence of pExpr */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1031
    int termSortOrder; /* Sort order for this term */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1032
    int iColumn;       /* The i-th column of the index.  -1 for rowid */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1033
    int iSortOrder;    /* 1 for DESC, 0 for ASC on the i-th index term */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1034
    const char *zColl; /* Name of the collating sequence for i-th index term */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1035
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1036
    pExpr = pTerm->pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1037
    if( pExpr->op!=TK_COLUMN || pExpr->iTable!=base ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1038
      /* Can not use an index sort on anything that is not a column in the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1039
      ** left-most table of the FROM clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1040
      break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1041
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1042
    pColl = sqlite3ExprCollSeq(pParse, pExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1043
    if( !pColl ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1044
      pColl = db->pDfltColl;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1045
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1046
    if( i<pIdx->nColumn ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1047
      iColumn = pIdx->aiColumn[i];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1048
      if( iColumn==pIdx->pTable->iPKey ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1049
        iColumn = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1050
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1051
      iSortOrder = pIdx->aSortOrder[i];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1052
      zColl = pIdx->azColl[i];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1053
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1054
      iColumn = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1055
      iSortOrder = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1056
      zColl = pColl->zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1057
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1058
    if( pExpr->iColumn!=iColumn || sqlite3StrICmp(pColl->zName, zColl) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1059
      /* Term j of the ORDER BY clause does not match column i of the index */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1060
      if( i<nEqCol ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1061
        /* If an index column that is constrained by == fails to match an
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1062
        ** ORDER BY term, that is OK.  Just ignore that column of the index
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1063
        */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1064
        continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1065
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1066
        /* If an index column fails to match and is not constrained by ==
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1067
        ** then the index cannot satisfy the ORDER BY constraint.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1068
        */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1069
        return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1070
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1071
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1072
    assert( pIdx->aSortOrder!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1073
    assert( pTerm->sortOrder==0 || pTerm->sortOrder==1 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1074
    assert( iSortOrder==0 || iSortOrder==1 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1075
    termSortOrder = iSortOrder ^ pTerm->sortOrder;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1076
    if( i>nEqCol ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1077
      if( termSortOrder!=sortOrder ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1078
        /* Indices can only be used if all ORDER BY terms past the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1079
        ** equality constraints are all either DESC or ASC. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1080
        return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1081
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1082
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1083
      sortOrder = termSortOrder;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1084
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1085
    j++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1086
    pTerm++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1087
    if( iColumn<0 && !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1088
      /* If the indexed column is the primary key and everything matches
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1089
      ** so far and none of the ORDER BY terms to the right reference other
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1090
      ** tables in the join, then we are assured that the index can be used 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1091
      ** to sort because the primary key is unique and so none of the other
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1092
      ** columns will make any difference
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1093
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1094
      j = nTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1095
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1096
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1097
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1098
  *pbRev = sortOrder!=0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1099
  if( j>=nTerm ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1100
    /* All terms of the ORDER BY clause are covered by this index so
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1101
    ** this index can be used for sorting. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1102
    return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1103
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1104
  if( pIdx->onError!=OE_None && i==pIdx->nColumn
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1105
      && !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1106
    /* All terms of this index match some prefix of the ORDER BY clause
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1107
    ** and the index is UNIQUE and no terms on the tail of the ORDER BY
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1108
    ** clause reference other tables in a join.  If this is all true then
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1109
    ** the order by clause is superfluous. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1110
    return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1111
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1112
  return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1113
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1114
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1115
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1116
** Check table to see if the ORDER BY clause in pOrderBy can be satisfied
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1117
** by sorting in order of ROWID.  Return true if so and set *pbRev to be
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1118
** true for reverse ROWID and false for forward ROWID order.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1119
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1120
static int sortableByRowid(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1121
  int base,               /* Cursor number for table to be sorted */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1122
  ExprList *pOrderBy,     /* The ORDER BY clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1123
  ExprMaskSet *pMaskSet,  /* Mapping from tables to bitmaps */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1124
  int *pbRev              /* Set to 1 if ORDER BY is DESC */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1125
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1126
  Expr *p;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1127
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1128
  assert( pOrderBy!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1129
  assert( pOrderBy->nExpr>0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1130
  p = pOrderBy->a[0].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1131
  if( p->op==TK_COLUMN && p->iTable==base && p->iColumn==-1
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1132
    && !referencesOtherTables(pOrderBy, pMaskSet, 1, base) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1133
    *pbRev = pOrderBy->a[0].sortOrder;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1134
    return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1135
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1136
  return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1137
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1138
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1139
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1140
** Prepare a crude estimate of the logarithm of the input value.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1141
** The results need not be exact.  This is only used for estimating
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1142
** the total cost of performing operatings with O(logN) or O(NlogN)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1143
** complexity.  Because N is just a guess, it is no great tragedy if
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1144
** logN is a little off.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1145
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1146
static double estLog(double N){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1147
  double logN = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1148
  double x = 10;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1149
  while( N>x ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1150
    logN += 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1151
    x *= 10;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1152
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1153
  return logN;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1154
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1155
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1156
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1157
** Two routines for printing the content of an sqlite3_index_info
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1158
** structure.  Used for testing and debugging only.  If neither
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1159
** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1160
** are no-ops.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1161
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1162
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_DEBUG)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1163
static void TRACE_IDX_INPUTS(sqlite3_index_info *p){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1164
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1165
  if( !sqlite3_where_trace ) return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1166
  for(i=0; i<p->nConstraint; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1167
    sqlite3DebugPrintf("  constraint[%d]: col=%d termid=%d op=%d usabled=%d\n",
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1168
       i,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1169
       p->aConstraint[i].iColumn,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1170
       p->aConstraint[i].iTermOffset,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1171
       p->aConstraint[i].op,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1172
       p->aConstraint[i].usable);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1173
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1174
  for(i=0; i<p->nOrderBy; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1175
    sqlite3DebugPrintf("  orderby[%d]: col=%d desc=%d\n",
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1176
       i,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1177
       p->aOrderBy[i].iColumn,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1178
       p->aOrderBy[i].desc);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1179
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1180
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1181
static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1182
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1183
  if( !sqlite3_where_trace ) return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1184
  for(i=0; i<p->nConstraint; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1185
    sqlite3DebugPrintf("  usage[%d]: argvIdx=%d omit=%d\n",
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1186
       i,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1187
       p->aConstraintUsage[i].argvIndex,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1188
       p->aConstraintUsage[i].omit);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1189
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1190
  sqlite3DebugPrintf("  idxNum=%d\n", p->idxNum);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1191
  sqlite3DebugPrintf("  idxStr=%s\n", p->idxStr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1192
  sqlite3DebugPrintf("  orderByConsumed=%d\n", p->orderByConsumed);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1193
  sqlite3DebugPrintf("  estimatedCost=%g\n", p->estimatedCost);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1194
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1195
#else
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1196
#define TRACE_IDX_INPUTS(A)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1197
#define TRACE_IDX_OUTPUTS(A)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1198
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1199
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1200
#ifndef SQLITE_OMIT_VIRTUALTABLE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1201
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1202
** Compute the best index for a virtual table.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1203
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1204
** The best index is computed by the xBestIndex method of the virtual
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1205
** table module.  This routine is really just a wrapper that sets up
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1206
** the sqlite3_index_info structure that is used to communicate with
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1207
** xBestIndex.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1208
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1209
** In a join, this routine might be called multiple times for the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1210
** same virtual table.  The sqlite3_index_info structure is created
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1211
** and initialized on the first invocation and reused on all subsequent
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1212
** invocations.  The sqlite3_index_info structure is also used when
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1213
** code is generated to access the virtual table.  The whereInfoDelete() 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1214
** routine takes care of freeing the sqlite3_index_info structure after
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1215
** everybody has finished with it.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1216
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1217
static double bestVirtualIndex(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1218
  Parse *pParse,                 /* The parsing context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1219
  WhereClause *pWC,              /* The WHERE clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1220
  SrcList::SrcList_item *pSrc,     /* The FROM clause term to search */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1221
  Bitmask notReady,              /* Mask of cursors that are not available */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1222
  ExprList *pOrderBy,            /* The order by clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1223
  int orderByUsable,             /* True if we can potential sort */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1224
  sqlite3_index_info **ppIdxInfo /* Index information passed to xBestIndex */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1225
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1226
  Table *pTab = pSrc->pTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1227
  sqlite3_index_info *pIdxInfo;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1228
  sqlite3_index_info::sqlite3_index_constraint *pIdxCons;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1229
  sqlite3_index_info::sqlite3_index_orderby *pIdxOrderBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1230
  sqlite3_index_info::sqlite3_index_constraint_usage *pUsage;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1231
  WhereTerm *pTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1232
  int i, j;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1233
  int nOrderBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1234
  int rc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1235
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1236
  /* If the sqlite3_index_info structure has not been previously
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1237
  ** allocated and initialized for this virtual table, then allocate
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1238
  ** and initialize it now
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1239
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1240
  pIdxInfo = *ppIdxInfo;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1241
  if( pIdxInfo==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1242
    WhereTerm *pTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1243
    int nTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1244
    WHERETRACE(("Recomputing index info for %s...\n", pTab->zName));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1245
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1246
    /* Count the number of possible WHERE clause constraints referring
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1247
    ** to this virtual table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1248
    for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1249
      if( pTerm->leftCursor != pSrc->iCursor ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1250
      if( pTerm->eOperator==WO_IN ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1251
      if( pTerm->eOperator==WO_ISNULL ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1252
      nTerm++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1253
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1254
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1255
    /* If the ORDER BY clause contains only columns in the current 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1256
    ** virtual table then allocate space for the aOrderBy part of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1257
    ** the sqlite3_index_info structure.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1258
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1259
    nOrderBy = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1260
    if( pOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1261
      for(i=0; i<pOrderBy->nExpr; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1262
        Expr *pExpr = pOrderBy->a[i].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1263
        if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1264
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1265
      if( i==pOrderBy->nExpr ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1266
        nOrderBy = pOrderBy->nExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1267
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1268
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1269
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1270
    /* Allocate the sqlite3_index_info structure
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1271
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1272
    pIdxInfo = (sqlite3_index_info*)sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1273
                             + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1274
                             + sizeof(*pIdxOrderBy)*nOrderBy );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1275
    if( pIdxInfo==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1276
      sqlite3ErrorMsg(pParse, "out of memory");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1277
      return 0.0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1278
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1279
    *ppIdxInfo = pIdxInfo;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1280
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1281
    /* Initialize the structure.  The sqlite3_index_info structure contains
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1282
    ** many fields that are declared "const" to prevent xBestIndex from
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1283
    ** changing them.  We have to do some funky casting in order to
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1284
    ** initialize those fields.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1285
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1286
	pIdxCons = (sqlite3_index_info::sqlite3_index_constraint*)&pIdxInfo[1];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1287
	pIdxOrderBy = (sqlite3_index_info::sqlite3_index_orderby*)&pIdxCons[nTerm];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1288
	pUsage = (sqlite3_index_info::sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1289
    *(int*)&pIdxInfo->nConstraint = nTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1290
    *(int*)&pIdxInfo->nOrderBy = nOrderBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1291
	*(sqlite3_index_info::sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1292
	*(sqlite3_index_info::sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1293
	*(sqlite3_index_info::sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage =
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1294
                                                                     pUsage;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1295
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1296
    for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1297
      if( pTerm->leftCursor != pSrc->iCursor ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1298
      if( pTerm->eOperator==WO_IN ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1299
      if( pTerm->eOperator==WO_ISNULL ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1300
      pIdxCons[j].iColumn = pTerm->leftColumn;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1301
      pIdxCons[j].iTermOffset = i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1302
      pIdxCons[j].op = pTerm->eOperator;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1303
      /* The direct assignment in the previous line is possible only because
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1304
      ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical.  The
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1305
      ** following asserts verify this fact. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1306
      assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1307
      assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1308
      assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1309
      assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1310
      assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1311
      assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1312
      assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1313
      j++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1314
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1315
    for(i=0; i<nOrderBy; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1316
      Expr *pExpr = pOrderBy->a[i].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1317
      pIdxOrderBy[i].iColumn = pExpr->iColumn;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1318
      pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1319
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1320
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1321
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1322
  /* At this point, the sqlite3_index_info structure that pIdxInfo points
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1323
  ** to will have been initialized, either during the current invocation or
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1324
  ** during some prior invocation.  Now we just have to customize the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1325
  ** details of pIdxInfo for the current invocation and pass it to
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1326
  ** xBestIndex.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1327
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1328
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1329
  /* The module name must be defined. Also, by this point there must
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1330
  ** be a pointer to an sqlite3_vtab structure. Otherwise
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1331
  ** sqlite3ViewGetColumnNames() would have picked up the error. 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1332
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1333
  assert( pTab->azModuleArg && pTab->azModuleArg[0] );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1334
  assert( pTab->pVtab );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1335
#if 0
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1336
  if( pTab->pVtab==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1337
    sqlite3ErrorMsg(pParse, "undefined module %s for table %s",
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1338
        pTab->azModuleArg[0], pTab->zName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1339
    return 0.0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1340
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1341
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1342
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1343
  /* Set the aConstraint[].usable fields and initialize all 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1344
  ** output variables to zero.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1345
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1346
  ** aConstraint[].usable is true for constraints where the right-hand
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1347
  ** side contains only references to tables to the left of the current
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1348
  ** table.  In other words, if the constraint is of the form:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1349
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1350
  **           column = expr
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1351
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1352
  ** and we are evaluating a join, then the constraint on column is 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1353
  ** only valid if all tables referenced in expr occur to the left
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1354
  ** of the table containing column.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1355
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1356
  ** The aConstraints[] array contains entries for all constraints
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1357
  ** on the current table.  That way we only have to compute it once
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1358
  ** even though we might try to pick the best index multiple times.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1359
  ** For each attempt at picking an index, the order of tables in the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1360
  ** join might be different so we have to recompute the usable flag
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1361
  ** each time.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1362
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1363
  pIdxCons = *(sqlite3_index_info::sqlite3_index_constraint**)&pIdxInfo->aConstraint;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1364
  pUsage = pIdxInfo->aConstraintUsage;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1365
  for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1366
    j = pIdxCons->iTermOffset;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1367
    pTerm = &pWC->a[j];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1368
    pIdxCons->usable =  (pTerm->prereqRight & notReady)==0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1369
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1370
  memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1371
  if( pIdxInfo->needToFreeIdxStr ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1372
    sqlite3_free(pIdxInfo->idxStr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1373
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1374
  pIdxInfo->idxStr = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1375
  pIdxInfo->idxNum = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1376
  pIdxInfo->needToFreeIdxStr = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1377
  pIdxInfo->orderByConsumed = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1378
  pIdxInfo->estimatedCost = SQLITE_BIG_DBL / 2.0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1379
  nOrderBy = pIdxInfo->nOrderBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1380
  if( pIdxInfo->nOrderBy && !orderByUsable ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1381
    *(int*)&pIdxInfo->nOrderBy = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1382
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1383
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1384
  sqlite3SafetyOff(pParse->db);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1385
  WHERETRACE(("xBestIndex for %s\n", pTab->zName));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1386
  TRACE_IDX_INPUTS(pIdxInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1387
  rc = pTab->pVtab->pModule->xBestIndex(pTab->pVtab, pIdxInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1388
  TRACE_IDX_OUTPUTS(pIdxInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1389
  if( rc!=SQLITE_OK ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1390
    if( rc==SQLITE_NOMEM ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1391
      pParse->db->mallocFailed = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1392
    }else {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1393
      sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1394
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1395
    sqlite3SafetyOn(pParse->db);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1396
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1397
    rc = sqlite3SafetyOn(pParse->db);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1398
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1399
  *(int*)&pIdxInfo->nOrderBy = nOrderBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1400
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1401
  return pIdxInfo->estimatedCost;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1402
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1403
#endif /* SQLITE_OMIT_VIRTUALTABLE */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1404
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1405
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1406
** Find the best index for accessing a particular table.  Return a pointer
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1407
** to the index, flags that describe how the index should be used, the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1408
** number of equality constraints, and the "cost" for this index.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1409
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1410
** The lowest cost index wins.  The cost is an estimate of the amount of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1411
** CPU and disk I/O need to process the request using the selected index.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1412
** Factors that influence cost include:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1413
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1414
**    *  The estimated number of rows that will be retrieved.  (The
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1415
**       fewer the better.)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1416
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1417
**    *  Whether or not sorting must occur.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1418
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1419
**    *  Whether or not there must be separate lookups in the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1420
**       index and in the main table.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1421
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1422
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1423
static double bestIndex(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1424
  Parse *pParse,              /* The parsing context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1425
  WhereClause *pWC,           /* The WHERE clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1426
  SrcList::SrcList_item *pSrc,  /* The FROM clause term to search */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1427
  Bitmask notReady,           /* Mask of cursors that are not available */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1428
  ExprList *pOrderBy,         /* The order by clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1429
  Index **ppIndex,            /* Make *ppIndex point to the best index */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1430
  int *pFlags,                /* Put flags describing this choice in *pFlags */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1431
  int *pnEq                   /* Put the number of == or IN constraints here */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1432
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1433
  WhereTerm *pTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1434
  Index *bestIdx = 0;         /* Index that gives the lowest cost */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1435
  double lowestCost;          /* The cost of using bestIdx */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1436
  int bestFlags = 0;          /* Flags associated with bestIdx */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1437
  int bestNEq = 0;            /* Best value for nEq */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1438
  int iCur = pSrc->iCursor;   /* The cursor of the table to be accessed */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1439
  Index *pProbe;              /* An index we are evaluating */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1440
  int rev;                    /* True to scan in reverse order */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1441
  int flags;                  /* Flags associated with pProbe */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1442
  int nEq;                    /* Number of == or IN constraints */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1443
  int eqTermMask;             /* Mask of valid equality operators */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1444
  double cost;                /* Cost of using pProbe */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1445
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1446
  WHERETRACE(("bestIndex: tbl=%s notReady=%x\n", pSrc->pTab->zName, notReady));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1447
  lowestCost = SQLITE_BIG_DBL;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1448
  pProbe = pSrc->pTab->pIndex;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1449
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1450
  /* If the table has no indices and there are no terms in the where
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1451
  ** clause that refer to the ROWID, then we will never be able to do
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1452
  ** anything other than a full table scan on this table.  We might as
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1453
  ** well put it first in the join order.  That way, perhaps it can be
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1454
  ** referenced by other tables in the join.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1455
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1456
  if( pProbe==0 &&
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1457
     findTerm(pWC, iCur, -1, 0, WO_EQ|WO_IN|WO_LT|WO_LE|WO_GT|WO_GE,0)==0 &&
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1458
     (pOrderBy==0 || !sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev)) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1459
    *pFlags = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1460
    *ppIndex = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1461
    *pnEq = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1462
    return 0.0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1463
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1464
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1465
  /* Check for a rowid=EXPR or rowid IN (...) constraints
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1466
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1467
  pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1468
  if( pTerm ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1469
    Expr *pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1470
    *ppIndex = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1471
    bestFlags = WHERE_ROWID_EQ;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1472
    if( pTerm->eOperator & WO_EQ ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1473
      /* Rowid== is always the best pick.  Look no further.  Because only
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1474
      ** a single row is generated, output is always in sorted order */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1475
      *pFlags = WHERE_ROWID_EQ | WHERE_UNIQUE;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1476
      *pnEq = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1477
      WHERETRACE(("... best is rowid\n"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1478
      return 0.0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1479
    }else if( (pExpr = pTerm->pExpr)->pList!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1480
      /* Rowid IN (LIST): cost is NlogN where N is the number of list
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1481
      ** elements.  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1482
      lowestCost = pExpr->pList->nExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1483
      lowestCost *= estLog(lowestCost);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1484
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1485
      /* Rowid IN (SELECT): cost is NlogN where N is the number of rows
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1486
      ** in the result of the inner select.  We have no way to estimate
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1487
      ** that value so make a wild guess. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1488
      lowestCost = 200;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1489
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1490
    WHERETRACE(("... rowid IN cost: %.9g\n", lowestCost));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1491
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1492
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1493
  /* Estimate the cost of a table scan.  If we do not know how many
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1494
  ** entries are in the table, use 1 million as a guess.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1495
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1496
  cost = pProbe ? pProbe->aiRowEst[0] : 1000000;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1497
  WHERETRACE(("... table scan base cost: %.9g\n", cost));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1498
  flags = WHERE_ROWID_RANGE;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1499
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1500
  /* Check for constraints on a range of rowids in a table scan.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1501
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1502
  pTerm = findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE|WO_GT|WO_GE, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1503
  if( pTerm ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1504
    if( findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE, 0) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1505
      flags |= WHERE_TOP_LIMIT;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1506
      cost /= 3;  /* Guess that rowid<EXPR eliminates two-thirds or rows */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1507
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1508
    if( findTerm(pWC, iCur, -1, notReady, WO_GT|WO_GE, 0) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1509
      flags |= WHERE_BTM_LIMIT;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1510
      cost /= 3;  /* Guess that rowid>EXPR eliminates two-thirds of rows */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1511
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1512
    WHERETRACE(("... rowid range reduces cost to %.9g\n", cost));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1513
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1514
    flags = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1515
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1516
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1517
  /* If the table scan does not satisfy the ORDER BY clause, increase
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1518
  ** the cost by NlogN to cover the expense of sorting. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1519
  if( pOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1520
    if( sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1521
      flags |= WHERE_ORDERBY|WHERE_ROWID_RANGE;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1522
      if( rev ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1523
        flags |= WHERE_REVERSE;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1524
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1525
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1526
      cost += cost*estLog(cost);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1527
      WHERETRACE(("... sorting increases cost to %.9g\n", cost));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1528
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1529
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1530
  if( cost<lowestCost ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1531
    lowestCost = cost;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1532
    bestFlags = flags;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1533
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1534
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1535
  /* If the pSrc table is the right table of a LEFT JOIN then we may not
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1536
  ** use an index to satisfy IS NULL constraints on that table.  This is
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1537
  ** because columns might end up being NULL if the table does not match -
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1538
  ** a circumstance which the index cannot help us discover.  Ticket #2177.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1539
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1540
  if( (pSrc->jointype & JT_LEFT)!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1541
    eqTermMask = WO_EQ|WO_IN;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1542
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1543
    eqTermMask = WO_EQ|WO_IN|WO_ISNULL;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1544
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1545
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1546
  /* Look at each index.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1547
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1548
  for(; pProbe; pProbe=pProbe->pNext){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1549
    int i;                       /* Loop counter */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1550
    double inMultiplier = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1551
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1552
    WHERETRACE(("... index %s:\n", pProbe->zName));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1553
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1554
    /* Count the number of columns in the index that are satisfied
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1555
    ** by x=EXPR constraints or x IN (...) constraints.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1556
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1557
    flags = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1558
    for(i=0; i<pProbe->nColumn; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1559
      int j = pProbe->aiColumn[i];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1560
      pTerm = findTerm(pWC, iCur, j, notReady, eqTermMask, pProbe);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1561
      if( pTerm==0 ) break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1562
      flags |= WHERE_COLUMN_EQ;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1563
      if( pTerm->eOperator & WO_IN ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1564
        Expr *pExpr = pTerm->pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1565
        flags |= WHERE_COLUMN_IN;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1566
        if( pExpr->pSelect!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1567
          inMultiplier *= 25;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1568
        }else if( pExpr->pList!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1569
          inMultiplier *= pExpr->pList->nExpr + 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1570
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1571
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1572
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1573
    cost = pProbe->aiRowEst[i] * inMultiplier * estLog(inMultiplier);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1574
    nEq = i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1575
    if( pProbe->onError!=OE_None && (flags & WHERE_COLUMN_IN)==0
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1576
         && nEq==pProbe->nColumn ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1577
      flags |= WHERE_UNIQUE;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1578
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1579
    WHERETRACE(("...... nEq=%d inMult=%.9g cost=%.9g\n",nEq,inMultiplier,cost));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1580
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1581
    /* Look for range constraints
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1582
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1583
    if( nEq<pProbe->nColumn ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1584
      int j = pProbe->aiColumn[nEq];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1585
      pTerm = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pProbe);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1586
      if( pTerm ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1587
        flags |= WHERE_COLUMN_RANGE;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1588
        if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pProbe) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1589
          flags |= WHERE_TOP_LIMIT;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1590
          cost /= 3;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1591
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1592
        if( findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pProbe) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1593
          flags |= WHERE_BTM_LIMIT;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1594
          cost /= 3;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1595
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1596
        WHERETRACE(("...... range reduces cost to %.9g\n", cost));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1597
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1598
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1599
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1600
    /* Add the additional cost of sorting if that is a factor.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1601
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1602
    if( pOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1603
      if( (flags & WHERE_COLUMN_IN)==0 &&
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1604
           isSortingIndex(pParse,pWC->pMaskSet,pProbe,iCur,pOrderBy,nEq,&rev) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1605
        if( flags==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1606
          flags = WHERE_COLUMN_RANGE;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1607
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1608
        flags |= WHERE_ORDERBY;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1609
        if( rev ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1610
          flags |= WHERE_REVERSE;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1611
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1612
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1613
        cost += cost*estLog(cost);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1614
        WHERETRACE(("...... orderby increases cost to %.9g\n", cost));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1615
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1616
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1617
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1618
    /* Check to see if we can get away with using just the index without
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1619
    ** ever reading the table.  If that is the case, then halve the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1620
    ** cost of this index.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1621
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1622
    if( flags && pSrc->colUsed < (((Bitmask)1)<<(BMS-1)) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1623
      Bitmask m = pSrc->colUsed;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1624
      int j;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1625
      for(j=0; j<pProbe->nColumn; j++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1626
        int x = pProbe->aiColumn[j];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1627
        if( x<BMS-1 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1628
          m &= ~(((Bitmask)1)<<x);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1629
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1630
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1631
      if( m==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1632
        flags |= WHERE_IDX_ONLY;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1633
        cost /= 2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1634
        WHERETRACE(("...... idx-only reduces cost to %.9g\n", cost));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1635
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1636
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1637
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1638
    /* If this index has achieved the lowest cost so far, then use it.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1639
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1640
    if( flags && cost < lowestCost ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1641
      bestIdx = pProbe;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1642
      lowestCost = cost;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1643
      bestFlags = flags;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1644
      bestNEq = nEq;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1645
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1646
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1647
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1648
  /* Report the best result
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1649
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1650
  *ppIndex = bestIdx;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1651
  WHERETRACE(("best index is %s, cost=%.9g, flags=%x, nEq=%d\n",
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1652
        bestIdx ? bestIdx->zName : "(none)", lowestCost, bestFlags, bestNEq));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1653
  *pFlags = bestFlags | eqTermMask;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1654
  *pnEq = bestNEq;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1655
  return lowestCost;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1656
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1657
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1658
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1659
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1660
** Disable a term in the WHERE clause.  Except, do not disable the term
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1661
** if it controls a LEFT OUTER JOIN and it did not originate in the ON
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1662
** or USING clause of that join.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1663
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1664
** Consider the term t2.z='ok' in the following queries:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1665
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1666
**   (1)  SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x WHERE t2.z='ok'
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1667
**   (2)  SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok'
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1668
**   (3)  SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok'
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1669
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1670
** The t2.z='ok' is disabled in the in (2) because it originates
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1671
** in the ON clause.  The term is disabled in (3) because it is not part
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1672
** of a LEFT OUTER JOIN.  In (1), the term is not disabled.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1673
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1674
** Disabling a term causes that term to not be tested in the inner loop
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1675
** of the join.  Disabling is an optimization.  When terms are satisfied
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1676
** by indices, we disable them to prevent redundant tests in the inner
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1677
** loop.  We would get the correct results if nothing were ever disabled,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1678
** but joins might run a little slower.  The trick is to disable as much
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1679
** as we can without disabling too much.  If we disabled in (1), we'd get
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1680
** the wrong answer.  See ticket #813.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1681
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1682
static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1683
  if( pTerm
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1684
      && (pTerm->flags & TERM_CODED)==0
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1685
      && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1686
  ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1687
    pTerm->flags |= TERM_CODED;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1688
    if( pTerm->iParent>=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1689
      WhereTerm *pOther = &pTerm->pWC->a[pTerm->iParent];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1690
      if( (--pOther->nChild)==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1691
        disableTerm(pLevel, pOther);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1692
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1693
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1694
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1695
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1696
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1697
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1698
** Generate code that builds a probe for an index.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1699
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1700
** There should be nColumn values on the stack.  The index
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1701
** to be probed is pIdx.  Pop the values from the stack and
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1702
** replace them all with a single record that is the index
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1703
** problem.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1704
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1705
static void buildIndexProbe(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1706
  Vdbe *v,        /* Generate code into this VM */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1707
  int nColumn,    /* The number of columns to check for NULL */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1708
  Index *pIdx     /* Index that we will be searching */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1709
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1710
  sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1711
  sqlite3IndexAffinityStr(v, pIdx);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1712
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1713
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1714
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1715
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1716
** Generate code for a single equality term of the WHERE clause.  An equality
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1717
** term can be either X=expr or X IN (...).   pTerm is the term to be 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1718
** coded.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1719
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1720
** The current value for the constraint is left on the top of the stack.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1721
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1722
** For a constraint of the form X=expr, the expression is evaluated and its
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1723
** result is left on the stack.  For constraints of the form X IN (...)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1724
** this routine sets up a loop that will iterate over all values of X.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1725
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1726
static void codeEqualityTerm(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1727
  Parse *pParse,      /* The parsing context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1728
  WhereTerm *pTerm,   /* The term of the WHERE clause to be coded */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1729
  WhereLevel *pLevel  /* When level of the FROM clause we are working on */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1730
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1731
  Expr *pX = pTerm->pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1732
  Vdbe *v = pParse->pVdbe;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1733
  if( pX->op==TK_EQ ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1734
    sqlite3ExprCode(pParse, pX->pRight);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1735
  }else if( pX->op==TK_ISNULL ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1736
    sqlite3VdbeAddOp(v, OP_Null, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1737
#ifndef SQLITE_OMIT_SUBQUERY
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1738
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1739
    int eType;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1740
    int iTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1741
	WhereLevel::InLoop *pIn;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1742
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1743
    assert( pX->op==TK_IN );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1744
    eType = sqlite3FindInIndex(pParse, pX, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1745
    iTab = pX->iTable;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1746
    sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1747
    VdbeComment((v, "# %.*s", pX->span.n, pX->span.z));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1748
    if( pLevel->nIn==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1749
      pLevel->nxt = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1750
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1751
    pLevel->nIn++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1752
	pLevel->aInLoop = (WhereLevel::InLoop*)sqlite3DbReallocOrFree(pParse->db, pLevel->aInLoop,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1753
                                    sizeof(pLevel->aInLoop[0])*pLevel->nIn);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1754
	pIn = (WhereLevel::InLoop*)pLevel->aInLoop;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1755
    if( pIn ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1756
      int op = ((eType==IN_INDEX_ROWID)?OP_Rowid:OP_Column);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1757
      pIn += pLevel->nIn - 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1758
      pIn->iCur = iTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1759
      pIn->topAddr = sqlite3VdbeAddOp(v, op, iTab, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1760
      sqlite3VdbeAddOp(v, OP_IsNull, -1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1761
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1762
      pLevel->nIn = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1763
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1764
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1765
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1766
  disableTerm(pLevel, pTerm);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1767
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1768
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1769
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1770
** Generate code that will evaluate all == and IN constraints for an
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1771
** index.  The values for all constraints are left on the stack.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1772
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1773
** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c).
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1774
** Suppose the WHERE clause is this:  a==5 AND b IN (1,2,3) AND c>5 AND c<10
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1775
** The index has as many as three equality constraints, but in this
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1776
** example, the third "c" value is an inequality.  So only two 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1777
** constraints are coded.  This routine will generate code to evaluate
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1778
** a==5 and b IN (1,2,3).  The current values for a and b will be left
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1779
** on the stack - a is the deepest and b the shallowest.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1780
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1781
** In the example above nEq==2.  But this subroutine works for any value
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1782
** of nEq including 0.  If nEq==0, this routine is nearly a no-op.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1783
** The only thing it does is allocate the pLevel->iMem memory cell.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1784
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1785
** This routine always allocates at least one memory cell and puts
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1786
** the address of that memory cell in pLevel->iMem.  The code that
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1787
** calls this routine will use pLevel->iMem to store the termination
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1788
** key value of the loop.  If one or more IN operators appear, then
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1789
** this routine allocates an additional nEq memory cells for internal
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1790
** use.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1791
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1792
static void codeAllEqualityTerms(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1793
  Parse *pParse,        /* Parsing context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1794
  WhereLevel *pLevel,   /* Which nested loop of the FROM we are coding */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1795
  WhereClause *pWC,     /* The WHERE clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1796
  Bitmask notReady      /* Which parts of FROM have not yet been coded */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1797
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1798
  int nEq = pLevel->nEq;        /* The number of == or IN constraints to code */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1799
  int termsInMem = 0;           /* If true, store value in mem[] cells */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1800
  Vdbe *v = pParse->pVdbe;      /* The virtual machine under construction */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1801
  Index *pIdx = pLevel->pIdx;   /* The index being used for this loop */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1802
  int iCur = pLevel->iTabCur;   /* The cursor of the table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1803
  WhereTerm *pTerm;             /* A single constraint term */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1804
  int j;                        /* Loop counter */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1805
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1806
  /* Figure out how many memory cells we will need then allocate them.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1807
  ** We always need at least one used to store the loop terminator
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1808
  ** value.  If there are IN operators we'll need one for each == or
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1809
  ** IN constraint.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1810
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1811
  pLevel->iMem = pParse->nMem++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1812
  if( pLevel->flags & WHERE_COLUMN_IN ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1813
    pParse->nMem += pLevel->nEq;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1814
    termsInMem = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1815
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1816
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1817
  /* Evaluate the equality constraints
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1818
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1819
  assert( pIdx->nColumn>=nEq );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1820
  for(j=0; j<nEq; j++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1821
    int k = pIdx->aiColumn[j];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1822
    pTerm = findTerm(pWC, iCur, k, notReady, pLevel->flags, pIdx);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1823
    if( pTerm==0 ) break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1824
    assert( (pTerm->flags & TERM_CODED)==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1825
    codeEqualityTerm(pParse, pTerm, pLevel);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1826
    if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1827
      sqlite3VdbeAddOp(v, OP_IsNull, termsInMem ? -1 : -(j+1), pLevel->brk);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1828
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1829
    if( termsInMem ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1830
      sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem+j+1, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1831
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1832
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1833
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1834
  /* Make sure all the constraint values are on the top of the stack
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1835
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1836
  if( termsInMem ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1837
    for(j=0; j<nEq; j++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1838
      sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem+j+1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1839
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1840
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1841
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1842
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1843
#if defined(SQLITE_TEST)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1844
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1845
** The following variable holds a text description of query plan generated
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1846
** by the most recent call to sqlite3WhereBegin().  Each call to WhereBegin
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1847
** overwrites the previous.  This information is used for testing and
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1848
** analysis only.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1849
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1850
char sqlite3_query_plan[BMS*2*40];  /* Text of the join */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1851
static int nQPlan = 0;              /* Next free slow in _query_plan[] */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1852
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1853
#endif /* SQLITE_TEST */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1854
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1855
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1856
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1857
** Free a WhereInfo structure
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1858
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1859
static void whereInfoFree(WhereInfo *pWInfo){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1860
  if( pWInfo ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1861
    int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1862
    for(i=0; i<pWInfo->nLevel; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1863
      sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1864
      if( pInfo ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1865
        if( pInfo->needToFreeIdxStr ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1866
          /* Coverage: Don't think this can be reached. By the time this
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1867
          ** function is called, the index-strings have been passed
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1868
          ** to the vdbe layer for deletion.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1869
          */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1870
          sqlite3_free(pInfo->idxStr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1871
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1872
        sqlite3_free(pInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1873
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1874
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1875
    sqlite3_free(pWInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1876
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1877
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1878
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1879
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1880
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1881
** Generate the beginning of the loop used for WHERE clause processing.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1882
** The return value is a pointer to an opaque structure that contains
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1883
** information needed to terminate the loop.  Later, the calling routine
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1884
** should invoke sqlite3WhereEnd() with the return value of this function
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1885
** in order to complete the WHERE clause processing.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1886
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1887
** If an error occurs, this routine returns NULL.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1888
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1889
** The basic idea is to do a nested loop, one loop for each table in
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1890
** the FROM clause of a select.  (INSERT and UPDATE statements are the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1891
** same as a SELECT with only a single table in the FROM clause.)  For
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1892
** example, if the SQL is this:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1893
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1894
**       SELECT * FROM t1, t2, t3 WHERE ...;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1895
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1896
** Then the code generated is conceptually like the following:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1897
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1898
**      foreach row1 in t1 do       \    Code generated
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1899
**        foreach row2 in t2 do      |-- by sqlite3WhereBegin()
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1900
**          foreach row3 in t3 do   /
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1901
**            ...
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1902
**          end                     \    Code generated
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1903
**        end                        |-- by sqlite3WhereEnd()
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1904
**      end                         /
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1905
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1906
** Note that the loops might not be nested in the order in which they
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1907
** appear in the FROM clause if a different order is better able to make
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1908
** use of indices.  Note also that when the IN operator appears in
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1909
** the WHERE clause, it might result in additional nested loops for
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1910
** scanning through all values on the right-hand side of the IN.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1911
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1912
** There are Btree cursors associated with each table.  t1 uses cursor
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1913
** number pTabList->a[0].iCursor.  t2 uses the cursor pTabList->a[1].iCursor.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1914
** And so forth.  This routine generates code to open those VDBE cursors
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1915
** and sqlite3WhereEnd() generates the code to close them.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1916
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1917
** The code that sqlite3WhereBegin() generates leaves the cursors named
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1918
** in pTabList pointing at their appropriate entries.  The [...] code
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1919
** can use OP_Column and OP_Rowid opcodes on these cursors to extract
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1920
** data from the various tables of the loop.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1921
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1922
** If the WHERE clause is empty, the foreach loops must each scan their
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1923
** entire tables.  Thus a three-way join is an O(N^3) operation.  But if
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1924
** the tables have indices and there are terms in the WHERE clause that
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1925
** refer to those indices, a complete table scan can be avoided and the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1926
** code will run much faster.  Most of the work of this routine is checking
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1927
** to see if there are indices that can be used to speed up the loop.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1928
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1929
** Terms of the WHERE clause are also used to limit which rows actually
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1930
** make it to the "..." in the middle of the loop.  After each "foreach",
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1931
** terms of the WHERE clause that use only terms in that loop and outer
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1932
** loops are evaluated and if false a jump is made around all subsequent
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1933
** inner loops (or around the "..." if the test occurs within the inner-
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1934
** most loop)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1935
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1936
** OUTER JOINS
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1937
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1938
** An outer join of tables t1 and t2 is conceptally coded as follows:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1939
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1940
**    foreach row1 in t1 do
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1941
**      flag = 0
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1942
**      foreach row2 in t2 do
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1943
**        start:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1944
**          ...
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1945
**          flag = 1
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1946
**      end
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1947
**      if flag==0 then
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1948
**        move the row2 cursor to a null row
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1949
**        goto start
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1950
**      fi
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1951
**    end
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1952
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1953
** ORDER BY CLAUSE PROCESSING
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1954
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1955
** *ppOrderBy is a pointer to the ORDER BY clause of a SELECT statement,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1956
** if there is one.  If there is no ORDER BY clause or if this routine
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1957
** is called from an UPDATE or DELETE statement, then ppOrderBy is NULL.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1958
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1959
** If an index can be used so that the natural output order of the table
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1960
** scan is correct for the ORDER BY clause, then that index is used and
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1961
** *ppOrderBy is set to NULL.  This is an optimization that prevents an
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1962
** unnecessary sort of the result set if an index appropriate for the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1963
** ORDER BY clause already exists.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1964
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1965
** If the where clause loops cannot be arranged to provide the correct
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1966
** output order, then the *ppOrderBy is unchanged.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1967
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1968
WhereInfo *sqlite3WhereBegin(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1969
  Parse *pParse,        /* The parser context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1970
  SrcList *pTabList,    /* A list of all tables to be scanned */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1971
  Expr *pWhere,         /* The WHERE clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1972
  ExprList **ppOrderBy  /* An ORDER BY clause, or NULL */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1973
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1974
  int i;                     /* Loop counter */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1975
  WhereInfo *pWInfo;         /* Will become the return value of this function */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1976
  Vdbe *v = pParse->pVdbe;   /* The virtual database engine */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1977
  int brk, cont = 0;         /* Addresses used during code generation */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1978
  Bitmask notReady;          /* Cursors that are not yet positioned */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1979
  WhereTerm *pTerm;          /* A single term in the WHERE clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1980
  ExprMaskSet maskSet;       /* The expression mask set */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1981
  WhereClause wc;            /* The WHERE clause is divided into these terms */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1982
  SrcList::SrcList_item *pTabItem;  /* A single entry from pTabList */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1983
  WhereLevel *pLevel;             /* A single level in the pWInfo list */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1984
  int iFrom;                      /* First unused FROM clause element */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1985
  int andFlags;              /* AND-ed combination of all wc.a[].flags */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1986
  sqlite3 *db;               /* Database connection */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1987
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1988
  /* The number of tables in the FROM clause is limited by the number of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1989
  ** bits in a Bitmask 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1990
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1991
  if( pTabList->nSrc>BMS ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1992
    sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1993
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1994
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1995
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1996
  /* Split the WHERE clause into separate subexpressions where each
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1997
  ** subexpression is separated by an AND operator.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1998
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1999
  initMaskSet(&maskSet);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2000
  whereClauseInit(&wc, pParse, &maskSet);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2001
  whereSplit(&wc, pWhere, TK_AND);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2002
    
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2003
  /* Allocate and initialize the WhereInfo structure that will become the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2004
  ** return value.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2005
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2006
  db = pParse->db;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2007
  pWInfo = (WhereInfo*)sqlite3DbMallocZero(db,  
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2008
                      sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2009
  if( db->mallocFailed ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2010
    goto whereBeginNoMem;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2011
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2012
  pWInfo->nLevel = pTabList->nSrc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2013
  pWInfo->pParse = pParse;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2014
  pWInfo->pTabList = pTabList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2015
  pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2016
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2017
  /* Special case: a WHERE clause that is constant.  Evaluate the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2018
  ** expression and either jump over all of the code or fall thru.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2019
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2020
  if( pWhere && (pTabList->nSrc==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2021
    sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2022
    pWhere = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2023
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2024
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2025
  /* Analyze all of the subexpressions.  Note that exprAnalyze() might
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2026
  ** add new virtual terms onto the end of the WHERE clause.  We do not
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2027
  ** want to analyze these virtual terms, so start analyzing at the end
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2028
  ** and work forward so that the added virtual terms are never processed.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2029
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2030
  for(i=0; i<pTabList->nSrc; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2031
    createMask(&maskSet, pTabList->a[i].iCursor);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2032
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2033
  exprAnalyzeAll(pTabList, &wc);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2034
  if( db->mallocFailed ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2035
    goto whereBeginNoMem;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2036
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2037
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2038
  /* Chose the best index to use for each table in the FROM clause.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2039
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2040
  ** This loop fills in the following fields:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2041
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2042
  **   pWInfo->a[].pIdx      The index to use for this level of the loop.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2043
  **   pWInfo->a[].flags     WHERE_xxx flags associated with pIdx
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2044
  **   pWInfo->a[].nEq       The number of == and IN constraints
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2045
  **   pWInfo->a[].iFrom     When term of the FROM clause is being coded
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2046
  **   pWInfo->a[].iTabCur   The VDBE cursor for the database table
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2047
  **   pWInfo->a[].iIdxCur   The VDBE cursor for the index
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2048
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2049
  ** This loop also figures out the nesting order of tables in the FROM
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2050
  ** clause.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2051
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2052
  notReady = ~(Bitmask)0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2053
  pTabItem = pTabList->a;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2054
  pLevel = pWInfo->a;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2055
  andFlags = ~0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2056
  WHERETRACE(("*** Optimizer Start ***\n"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2057
  for(i=iFrom=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2058
    Index *pIdx;                /* Index for FROM table at pTabItem */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2059
    int flags;                  /* Flags asssociated with pIdx */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2060
    int nEq;                    /* Number of == or IN constraints */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2061
    double cost;                /* The cost for pIdx */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2062
    int j;                      /* For looping over FROM tables */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2063
    Index *pBest = 0;           /* The best index seen so far */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2064
    int bestFlags = 0;          /* Flags associated with pBest */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2065
    int bestNEq = 0;            /* nEq associated with pBest */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2066
    double lowestCost;          /* Cost of the pBest */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2067
    int bestJ = 0;              /* The value of j */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2068
    Bitmask m;                  /* Bitmask value for j or bestJ */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2069
    int once = 0;               /* True when first table is seen */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2070
    sqlite3_index_info *pIndex; /* Current virtual index */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2071
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2072
    lowestCost = SQLITE_BIG_DBL;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2073
    for(j=iFrom, pTabItem=&pTabList->a[j]; j<pTabList->nSrc; j++, pTabItem++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2074
      int doNotReorder;  /* True if this table should not be reordered */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2075
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2076
      doNotReorder =  (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2077
      if( once && doNotReorder ) break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2078
      m = getMask(&maskSet, pTabItem->iCursor);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2079
      if( (m & notReady)==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2080
        if( j==iFrom ) iFrom++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2081
        continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2082
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2083
      assert( pTabItem->pTab );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2084
#ifndef SQLITE_OMIT_VIRTUALTABLE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2085
      if( IsVirtual(pTabItem->pTab) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2086
        sqlite3_index_info **ppIdxInfo = &pWInfo->a[j].pIdxInfo;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2087
        cost = bestVirtualIndex(pParse, &wc, pTabItem, notReady,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2088
                                ppOrderBy ? *ppOrderBy : 0, i==0,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2089
                                ppIdxInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2090
        flags = WHERE_VIRTUALTABLE;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2091
        pIndex = *ppIdxInfo;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2092
        if( pIndex && pIndex->orderByConsumed ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2093
          flags = WHERE_VIRTUALTABLE | WHERE_ORDERBY;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2094
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2095
        pIdx = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2096
        nEq = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2097
        if( (SQLITE_BIG_DBL/2.0)<cost ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2098
          /* The cost is not allowed to be larger than SQLITE_BIG_DBL (the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2099
          ** inital value of lowestCost in this loop. If it is, then
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2100
          ** the (cost<lowestCost) test below will never be true and
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2101
          ** pLevel->pBestIdx never set.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2102
          */ 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2103
          cost = (SQLITE_BIG_DBL/2.0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2104
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2105
      }else 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2106
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2107
      {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2108
        cost = bestIndex(pParse, &wc, pTabItem, notReady,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2109
                         (i==0 && ppOrderBy) ? *ppOrderBy : 0,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2110
                         &pIdx, &flags, &nEq);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2111
        pIndex = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2112
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2113
      if( cost<lowestCost ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2114
        once = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2115
        lowestCost = cost;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2116
        pBest = pIdx;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2117
        bestFlags = flags;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2118
        bestNEq = nEq;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2119
        bestJ = j;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2120
        pLevel->pBestIdx = pIndex;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2121
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2122
      if( doNotReorder ) break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2123
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2124
    WHERETRACE(("*** Optimizer choose table %d for loop %d\n", bestJ,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2125
           pLevel-pWInfo->a));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2126
    if( (bestFlags & WHERE_ORDERBY)!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2127
      *ppOrderBy = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2128
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2129
    andFlags &= bestFlags;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2130
    pLevel->flags = bestFlags;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2131
    pLevel->pIdx = pBest;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2132
    pLevel->nEq = bestNEq;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2133
    pLevel->aInLoop = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2134
    pLevel->nIn = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2135
    if( pBest ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2136
      pLevel->iIdxCur = pParse->nTab++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2137
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2138
      pLevel->iIdxCur = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2139
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2140
    notReady &= ~getMask(&maskSet, pTabList->a[bestJ].iCursor);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2141
    pLevel->iFrom = bestJ;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2142
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2143
  WHERETRACE(("*** Optimizer Finished ***\n"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2144
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2145
  /* If the total query only selects a single row, then the ORDER BY
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2146
  ** clause is irrelevant.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2147
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2148
  if( (andFlags & WHERE_UNIQUE)!=0 && ppOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2149
    *ppOrderBy = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2150
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2151
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2152
  /* Open all tables in the pTabList and any indices selected for
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2153
  ** searching those tables.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2154
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2155
  sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2156
  for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2157
    Table *pTab;     /* Table to open */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2158
    Index *pIx;      /* Index used to access pTab (if any) */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2159
    int iDb;         /* Index of database containing table/index */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2160
    int iIdxCur = pLevel->iIdxCur;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2161
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2162
#ifndef SQLITE_OMIT_EXPLAIN
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2163
    if( pParse->explain==2 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2164
      char *zMsg;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2165
	  SrcList::SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2166
      zMsg = sqlite3MPrintf(db, "TABLE %s", pItem->zName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2167
      if( pItem->zAlias ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2168
        zMsg = sqlite3MPrintf(db, "%z AS %s", zMsg, pItem->zAlias);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2169
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2170
      if( (pIx = pLevel->pIdx)!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2171
        zMsg = sqlite3MPrintf(db, "%z WITH INDEX %s", zMsg, pIx->zName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2172
      }else if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2173
        zMsg = sqlite3MPrintf(db, "%z USING PRIMARY KEY", zMsg);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2174
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2175
#ifndef SQLITE_OMIT_VIRTUALTABLE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2176
      else if( pLevel->pBestIdx ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2177
        sqlite3_index_info *pBestIdx = pLevel->pBestIdx;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2178
        zMsg = sqlite3MPrintf(db, "%z VIRTUAL TABLE INDEX %d:%s", zMsg,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2179
                    pBestIdx->idxNum, pBestIdx->idxStr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2180
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2181
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2182
      if( pLevel->flags & WHERE_ORDERBY ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2183
        zMsg = sqlite3MPrintf(db, "%z ORDER BY", zMsg);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2184
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2185
      sqlite3VdbeOp3(v, OP_Explain, i, pLevel->iFrom, zMsg, P3_DYNAMIC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2186
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2187
#endif /* SQLITE_OMIT_EXPLAIN */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2188
    pTabItem = &pTabList->a[pLevel->iFrom];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2189
    pTab = pTabItem->pTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2190
    iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2191
    if( pTab->isEphem || pTab->pSelect ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2192
#ifndef SQLITE_OMIT_VIRTUALTABLE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2193
    if( pLevel->pBestIdx ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2194
      int iCur = pTabItem->iCursor;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2195
      sqlite3VdbeOp3(v, OP_VOpen, iCur, 0, (const char*)pTab->pVtab, P3_VTAB);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2196
    }else
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2197
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2198
    if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2199
      sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, OP_OpenRead);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2200
      if( pTab->nCol<(sizeof(Bitmask)*8) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2201
        Bitmask b = pTabItem->colUsed;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2202
        int n = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2203
        for(; b; b=b>>1, n++){}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2204
        sqlite3VdbeChangeP2(v, sqlite3VdbeCurrentAddr(v)-1, n);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2205
        assert( n<=pTab->nCol );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2206
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2207
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2208
      sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2209
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2210
    pLevel->iTabCur = pTabItem->iCursor;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2211
    if( (pIx = pLevel->pIdx)!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2212
      KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2213
      assert( pIx->pSchema==pTab->pSchema );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2214
      sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2215
      VdbeComment((v, "# %s", pIx->zName));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2216
      sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIx->tnum,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2217
                     (char*)pKey, P3_KEYINFO_HANDOFF);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2218
      sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, pIx->nColumn+1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2219
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2220
    sqlite3CodeVerifySchema(pParse, iDb);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2221
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2222
  pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2223
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2224
  /* Generate the code to do the search.  Each iteration of the for
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2225
  ** loop below generates code for a single nested loop of the VM
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2226
  ** program.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2227
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2228
  notReady = ~(Bitmask)0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2229
  for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2230
    int j;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2231
    int iCur = pTabItem->iCursor;  /* The VDBE cursor for the table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2232
    Index *pIdx;       /* The index we will be using */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2233
    int nxt;           /* Where to jump to continue with the next IN case */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2234
    int iIdxCur;       /* The VDBE cursor for the index */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2235
    int omitTable;     /* True if we use the index only */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2236
    int bRev;          /* True if we need to scan in reverse order */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2237
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2238
    pTabItem = &pTabList->a[pLevel->iFrom];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2239
    iCur = pTabItem->iCursor;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2240
    pIdx = pLevel->pIdx;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2241
    iIdxCur = pLevel->iIdxCur;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2242
    bRev = (pLevel->flags & WHERE_REVERSE)!=0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2243
    omitTable = (pLevel->flags & WHERE_IDX_ONLY)!=0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2244
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2245
    /* Create labels for the "break" and "continue" instructions
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2246
    ** for the current loop.  Jump to brk to break out of a loop.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2247
    ** Jump to cont to go immediately to the next iteration of the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2248
    ** loop.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2249
    **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2250
    ** When there is an IN operator, we also have a "nxt" label that
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2251
    ** means to continue with the next IN value combination.  When
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2252
    ** there are no IN operators in the constraints, the "nxt" label
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2253
    ** is the same as "brk".
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2254
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2255
    brk = pLevel->brk = pLevel->nxt = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2256
    cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2257
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2258
    /* If this is the right table of a LEFT OUTER JOIN, allocate and
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2259
    ** initialize a memory cell that records if this table matches any
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2260
    ** row of the left table of the join.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2261
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2262
    if( pLevel->iFrom>0 && (pTabItem[0].jointype & JT_LEFT)!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2263
      if( !pParse->nMem ) pParse->nMem++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2264
      pLevel->iLeftJoin = pParse->nMem++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2265
      sqlite3VdbeAddOp(v, OP_MemInt, 0, pLevel->iLeftJoin);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2266
      VdbeComment((v, "# init LEFT JOIN no-match flag"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2267
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2268
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2269
#ifndef SQLITE_OMIT_VIRTUALTABLE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2270
    if( pLevel->pBestIdx ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2271
      /* Case 0:  The table is a virtual-table.  Use the VFilter and VNext
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2272
      **          to access the data.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2273
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2274
      int j;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2275
      sqlite3_index_info *pBestIdx = pLevel->pBestIdx;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2276
      int nConstraint = pBestIdx->nConstraint;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2277
	  sqlite3_index_info::sqlite3_index_constraint_usage *aUsage =
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2278
                                                  pBestIdx->aConstraintUsage;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2279
	  const sqlite3_index_info::sqlite3_index_constraint *aConstraint =
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2280
                                                  pBestIdx->aConstraint;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2281
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2282
      for(j=1; j<=nConstraint; j++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2283
        int k;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2284
        for(k=0; k<nConstraint; k++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2285
          if( aUsage[k].argvIndex==j ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2286
            int iTerm = aConstraint[k].iTermOffset;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2287
            sqlite3ExprCode(pParse, wc.a[iTerm].pExpr->pRight);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2288
            break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2289
          }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2290
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2291
        if( k==nConstraint ) break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2292
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2293
      sqlite3VdbeAddOp(v, OP_Integer, j-1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2294
      sqlite3VdbeAddOp(v, OP_Integer, pBestIdx->idxNum, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2295
      sqlite3VdbeOp3(v, OP_VFilter, iCur, brk, pBestIdx->idxStr,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2296
                      pBestIdx->needToFreeIdxStr ? P3_MPRINTF : P3_STATIC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2297
      pBestIdx->needToFreeIdxStr = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2298
      for(j=0; j<pBestIdx->nConstraint; j++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2299
        if( aUsage[j].omit ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2300
          int iTerm = aConstraint[j].iTermOffset;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2301
          disableTerm(pLevel, &wc.a[iTerm]);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2302
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2303
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2304
      pLevel->op = OP_VNext;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2305
      pLevel->p1 = iCur;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2306
      pLevel->p2 = sqlite3VdbeCurrentAddr(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2307
    }else
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2308
#endif /* SQLITE_OMIT_VIRTUALTABLE */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2309
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2310
    if( pLevel->flags & WHERE_ROWID_EQ ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2311
      /* Case 1:  We can directly reference a single row using an
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2312
      **          equality comparison against the ROWID field.  Or
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2313
      **          we reference multiple rows using a "rowid IN (...)"
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2314
      **          construct.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2315
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2316
      pTerm = findTerm(&wc, iCur, -1, notReady, WO_EQ|WO_IN, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2317
      assert( pTerm!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2318
      assert( pTerm->pExpr!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2319
      assert( pTerm->leftCursor==iCur );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2320
      assert( omitTable==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2321
      codeEqualityTerm(pParse, pTerm, pLevel);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2322
      nxt = pLevel->nxt;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2323
      sqlite3VdbeAddOp(v, OP_MustBeInt, 1, nxt);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2324
      sqlite3VdbeAddOp(v, OP_NotExists, iCur, nxt);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2325
      VdbeComment((v, "pk"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2326
      pLevel->op = OP_Noop;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2327
    }else if( pLevel->flags & WHERE_ROWID_RANGE ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2328
      /* Case 2:  We have an inequality comparison against the ROWID field.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2329
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2330
      int testOp = OP_Noop;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2331
      int start;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2332
      WhereTerm *pStart, *pEnd;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2333
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2334
      assert( omitTable==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2335
      pStart = findTerm(&wc, iCur, -1, notReady, WO_GT|WO_GE, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2336
      pEnd = findTerm(&wc, iCur, -1, notReady, WO_LT|WO_LE, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2337
      if( bRev ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2338
        pTerm = pStart;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2339
        pStart = pEnd;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2340
        pEnd = pTerm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2341
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2342
      if( pStart ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2343
        Expr *pX;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2344
        pX = pStart->pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2345
        assert( pX!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2346
        assert( pStart->leftCursor==iCur );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2347
        sqlite3ExprCode(pParse, pX->pRight);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2348
        sqlite3VdbeAddOp(v, OP_ForceInt, pX->op==TK_LE || pX->op==TK_GT, brk);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2349
        sqlite3VdbeAddOp(v, bRev ? OP_MoveLt : OP_MoveGe, iCur, brk);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2350
        VdbeComment((v, "pk"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2351
        disableTerm(pLevel, pStart);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2352
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2353
        sqlite3VdbeAddOp(v, bRev ? OP_Last : OP_Rewind, iCur, brk);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2354
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2355
      if( pEnd ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2356
        Expr *pX;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2357
        pX = pEnd->pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2358
        assert( pX!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2359
        assert( pEnd->leftCursor==iCur );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2360
        sqlite3ExprCode(pParse, pX->pRight);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2361
        pLevel->iMem = pParse->nMem++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2362
        sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2363
        if( pX->op==TK_LT || pX->op==TK_GT ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2364
          testOp = bRev ? OP_Le : OP_Ge;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2365
        }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2366
          testOp = bRev ? OP_Lt : OP_Gt;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2367
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2368
        disableTerm(pLevel, pEnd);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2369
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2370
      start = sqlite3VdbeCurrentAddr(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2371
      pLevel->op = bRev ? OP_Prev : OP_Next;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2372
      pLevel->p1 = iCur;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2373
      pLevel->p2 = start;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2374
      if( testOp!=OP_Noop ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2375
        sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2376
        sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2377
        sqlite3VdbeAddOp(v, testOp, SQLITE_AFF_NUMERIC|0x100, brk);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2378
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2379
    }else if( pLevel->flags & WHERE_COLUMN_RANGE ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2380
      /* Case 3: The WHERE clause term that refers to the right-most
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2381
      **         column of the index is an inequality.  For example, if
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2382
      **         the index is on (x,y,z) and the WHERE clause is of the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2383
      **         form "x=5 AND y<10" then this case is used.  Only the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2384
      **         right-most column can be an inequality - the rest must
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2385
      **         use the "==" and "IN" operators.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2386
      **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2387
      **         This case is also used when there are no WHERE clause
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2388
      **         constraints but an index is selected anyway, in order
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2389
      **         to force the output order to conform to an ORDER BY.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2390
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2391
      int start;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2392
      int nEq = pLevel->nEq;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2393
      int topEq=0;        /* True if top limit uses ==. False is strictly < */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2394
      int btmEq=0;        /* True if btm limit uses ==. False if strictly > */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2395
      int topOp, btmOp;   /* Operators for the top and bottom search bounds */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2396
      int testOp;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2397
      int topLimit = (pLevel->flags & WHERE_TOP_LIMIT)!=0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2398
      int btmLimit = (pLevel->flags & WHERE_BTM_LIMIT)!=0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2399
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2400
      /* Generate code to evaluate all constraint terms using == or IN
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2401
      ** and level the values of those terms on the stack.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2402
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2403
      codeAllEqualityTerms(pParse, pLevel, &wc, notReady);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2404
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2405
      /* Duplicate the equality term values because they will all be
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2406
      ** used twice: once to make the termination key and once to make the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2407
      ** start key.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2408
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2409
      for(j=0; j<nEq; j++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2410
        sqlite3VdbeAddOp(v, OP_Dup, nEq-1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2411
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2412
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2413
      /* Figure out what comparison operators to use for top and bottom 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2414
      ** search bounds. For an ascending index, the bottom bound is a > or >=
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2415
      ** operator and the top bound is a < or <= operator.  For a descending
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2416
      ** index the operators are reversed.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2417
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2418
      if( pIdx->aSortOrder[nEq]==SQLITE_SO_ASC ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2419
        topOp = WO_LT|WO_LE;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2420
        btmOp = WO_GT|WO_GE;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2421
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2422
        topOp = WO_GT|WO_GE;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2423
        btmOp = WO_LT|WO_LE;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2424
        SWAP(int, topLimit, btmLimit);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2425
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2426
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2427
      /* Generate the termination key.  This is the key value that
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2428
      ** will end the search.  There is no termination key if there
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2429
      ** are no equality terms and no "X<..." term.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2430
      **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2431
      ** 2002-Dec-04: On a reverse-order scan, the so-called "termination"
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2432
      ** key computed here really ends up being the start key.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2433
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2434
      nxt = pLevel->nxt;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2435
      if( topLimit ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2436
        Expr *pX;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2437
        int k = pIdx->aiColumn[j];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2438
        pTerm = findTerm(&wc, iCur, k, notReady, topOp, pIdx);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2439
        assert( pTerm!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2440
        pX = pTerm->pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2441
        assert( (pTerm->flags & TERM_CODED)==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2442
        sqlite3ExprCode(pParse, pX->pRight);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2443
        sqlite3VdbeAddOp(v, OP_IsNull, -(nEq*2+1), nxt);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2444
        topEq = pTerm->eOperator & (WO_LE|WO_GE);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2445
        disableTerm(pLevel, pTerm);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2446
        testOp = OP_IdxGE;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2447
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2448
        testOp = nEq>0 ? OP_IdxGE : OP_Noop;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2449
        topEq = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2450
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2451
      if( testOp!=OP_Noop ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2452
        int nCol = nEq + topLimit;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2453
        pLevel->iMem = pParse->nMem++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2454
        buildIndexProbe(v, nCol, pIdx);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2455
        if( bRev ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2456
          int op = topEq ? OP_MoveLe : OP_MoveLt;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2457
          sqlite3VdbeAddOp(v, op, iIdxCur, nxt);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2458
        }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2459
          sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2460
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2461
      }else if( bRev ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2462
        sqlite3VdbeAddOp(v, OP_Last, iIdxCur, brk);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2463
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2464
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2465
      /* Generate the start key.  This is the key that defines the lower
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2466
      ** bound on the search.  There is no start key if there are no
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2467
      ** equality terms and if there is no "X>..." term.  In
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2468
      ** that case, generate a "Rewind" instruction in place of the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2469
      ** start key search.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2470
      **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2471
      ** 2002-Dec-04: In the case of a reverse-order search, the so-called
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2472
      ** "start" key really ends up being used as the termination key.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2473
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2474
      if( btmLimit ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2475
        Expr *pX;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2476
        int k = pIdx->aiColumn[j];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2477
        pTerm = findTerm(&wc, iCur, k, notReady, btmOp, pIdx);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2478
        assert( pTerm!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2479
        pX = pTerm->pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2480
        assert( (pTerm->flags & TERM_CODED)==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2481
        sqlite3ExprCode(pParse, pX->pRight);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2482
        sqlite3VdbeAddOp(v, OP_IsNull, -(nEq+1), nxt);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2483
        btmEq = pTerm->eOperator & (WO_LE|WO_GE);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2484
        disableTerm(pLevel, pTerm);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2485
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2486
        btmEq = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2487
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2488
      if( nEq>0 || btmLimit ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2489
        int nCol = nEq + btmLimit;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2490
        buildIndexProbe(v, nCol, pIdx);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2491
        if( bRev ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2492
          pLevel->iMem = pParse->nMem++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2493
          sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2494
          testOp = OP_IdxLT;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2495
        }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2496
          int op = btmEq ? OP_MoveGe : OP_MoveGt;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2497
          sqlite3VdbeAddOp(v, op, iIdxCur, nxt);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2498
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2499
      }else if( bRev ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2500
        testOp = OP_Noop;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2501
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2502
        sqlite3VdbeAddOp(v, OP_Rewind, iIdxCur, brk);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2503
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2504
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2505
      /* Generate the the top of the loop.  If there is a termination
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2506
      ** key we have to test for that key and abort at the top of the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2507
      ** loop.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2508
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2509
      start = sqlite3VdbeCurrentAddr(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2510
      if( testOp!=OP_Noop ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2511
        sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2512
        sqlite3VdbeAddOp(v, testOp, iIdxCur, nxt);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2513
        if( (topEq && !bRev) || (!btmEq && bRev) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2514
          sqlite3VdbeChangeP3(v, -1, "+", P3_STATIC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2515
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2516
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2517
      if( topLimit | btmLimit ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2518
        sqlite3VdbeAddOp(v, OP_Column, iIdxCur, nEq);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2519
        sqlite3VdbeAddOp(v, OP_IsNull, 1, cont);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2520
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2521
      if( !omitTable ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2522
        sqlite3VdbeAddOp(v, OP_IdxRowid, iIdxCur, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2523
        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2524
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2525
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2526
      /* Record the instruction used to terminate the loop.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2527
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2528
      pLevel->op = bRev ? OP_Prev : OP_Next;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2529
      pLevel->p1 = iIdxCur;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2530
      pLevel->p2 = start;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2531
    }else if( pLevel->flags & WHERE_COLUMN_EQ ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2532
      /* Case 4:  There is an index and all terms of the WHERE clause that
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2533
      **          refer to the index using the "==" or "IN" operators.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2534
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2535
      int start;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2536
      int nEq = pLevel->nEq;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2537
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2538
      /* Generate code to evaluate all constraint terms using == or IN
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2539
      ** and leave the values of those terms on the stack.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2540
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2541
      codeAllEqualityTerms(pParse, pLevel, &wc, notReady);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2542
      nxt = pLevel->nxt;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2543
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2544
      /* Generate a single key that will be used to both start and terminate
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2545
      ** the search
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2546
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2547
      buildIndexProbe(v, nEq, pIdx);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2548
      sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2549
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2550
      /* Generate code (1) to move to the first matching element of the table.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2551
      ** Then generate code (2) that jumps to "nxt" after the cursor is past
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2552
      ** the last matching element of the table.  The code (1) is executed
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2553
      ** once to initialize the search, the code (2) is executed before each
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2554
      ** iteration of the scan to see if the scan has finished. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2555
      if( bRev ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2556
        /* Scan in reverse order */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2557
        sqlite3VdbeAddOp(v, OP_MoveLe, iIdxCur, nxt);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2558
        start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2559
        sqlite3VdbeAddOp(v, OP_IdxLT, iIdxCur, nxt);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2560
        pLevel->op = OP_Prev;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2561
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2562
        /* Scan in the forward order */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2563
        sqlite3VdbeAddOp(v, OP_MoveGe, iIdxCur, nxt);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2564
        start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2565
        sqlite3VdbeOp3(v, OP_IdxGE, iIdxCur, nxt, "+", P3_STATIC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2566
        pLevel->op = OP_Next;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2567
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2568
      if( !omitTable ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2569
        sqlite3VdbeAddOp(v, OP_IdxRowid, iIdxCur, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2570
        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2571
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2572
      pLevel->p1 = iIdxCur;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2573
      pLevel->p2 = start;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2574
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2575
      /* Case 5:  There is no usable index.  We must do a complete
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2576
      **          scan of the entire table.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2577
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2578
      assert( omitTable==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2579
      assert( bRev==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2580
      pLevel->op = OP_Next;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2581
      pLevel->p1 = iCur;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2582
      pLevel->p2 = 1 + sqlite3VdbeAddOp(v, OP_Rewind, iCur, brk);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2583
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2584
    notReady &= ~getMask(&maskSet, iCur);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2585
    sqlite3VdbeAddOp(v, OP_StackDepth, -1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2586
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2587
    /* Insert code to test every subexpression that can be completely
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2588
    ** computed using the current set of tables.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2589
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2590
    for(pTerm=wc.a, j=wc.nTerm; j>0; j--, pTerm++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2591
      Expr *pE;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2592
      if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2593
      if( (pTerm->prereqAll & notReady)!=0 ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2594
      pE = pTerm->pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2595
      assert( pE!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2596
      if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2597
        continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2598
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2599
      sqlite3ExprIfFalse(pParse, pE, cont, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2600
      pTerm->flags |= TERM_CODED;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2601
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2602
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2603
    /* For a LEFT OUTER JOIN, generate code that will record the fact that
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2604
    ** at least one row of the right table has matched the left table.  
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2605
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2606
    if( pLevel->iLeftJoin ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2607
      pLevel->top = sqlite3VdbeCurrentAddr(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2608
      sqlite3VdbeAddOp(v, OP_MemInt, 1, pLevel->iLeftJoin);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2609
      VdbeComment((v, "# record LEFT JOIN hit"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2610
      for(pTerm=wc.a, j=0; j<wc.nTerm; j++, pTerm++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2611
        if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2612
        if( (pTerm->prereqAll & notReady)!=0 ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2613
        assert( pTerm->pExpr );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2614
        sqlite3ExprIfFalse(pParse, pTerm->pExpr, cont, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2615
        pTerm->flags |= TERM_CODED;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2616
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2617
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2618
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2619
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2620
#ifdef SQLITE_TEST  /* For testing and debugging use only */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2621
  /* Record in the query plan information about the current table
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2622
  ** and the index used to access it (if any).  If the table itself
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2623
  ** is not used, its name is just '{}'.  If no index is used
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2624
  ** the index is listed as "{}".  If the primary key is used the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2625
  ** index name is '*'.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2626
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2627
  for(i=0; i<pTabList->nSrc; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2628
    char *z;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2629
    int n;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2630
    pLevel = &pWInfo->a[i];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2631
    pTabItem = &pTabList->a[pLevel->iFrom];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2632
    z = pTabItem->zAlias;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2633
    if( z==0 ) z = pTabItem->pTab->zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2634
    n = strlen(z);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2635
    if( n+nQPlan < sizeof(sqlite3_query_plan)-10 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2636
      if( pLevel->flags & WHERE_IDX_ONLY ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2637
        memcpy(&sqlite3_query_plan[nQPlan], "{}", 2);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2638
        nQPlan += 2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2639
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2640
        memcpy(&sqlite3_query_plan[nQPlan], z, n);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2641
        nQPlan += n;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2642
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2643
      sqlite3_query_plan[nQPlan++] = ' ';
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2644
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2645
    if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2646
      memcpy(&sqlite3_query_plan[nQPlan], "* ", 2);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2647
      nQPlan += 2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2648
    }else if( pLevel->pIdx==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2649
      memcpy(&sqlite3_query_plan[nQPlan], "{} ", 3);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2650
      nQPlan += 3;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2651
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2652
      n = strlen(pLevel->pIdx->zName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2653
      if( n+nQPlan < sizeof(sqlite3_query_plan)-2 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2654
        memcpy(&sqlite3_query_plan[nQPlan], pLevel->pIdx->zName, n);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2655
        nQPlan += n;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2656
        sqlite3_query_plan[nQPlan++] = ' ';
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2657
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2658
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2659
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2660
  while( nQPlan>0 && sqlite3_query_plan[nQPlan-1]==' ' ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2661
    sqlite3_query_plan[--nQPlan] = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2662
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2663
  sqlite3_query_plan[nQPlan] = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2664
  nQPlan = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2665
#endif /* SQLITE_TEST // Testing and debugging use only */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2666
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2667
  /* Record the continuation address in the WhereInfo structure.  Then
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2668
  ** clean up and return.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2669
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2670
  pWInfo->iContinue = cont;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2671
  whereClauseClear(&wc);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2672
  return pWInfo;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2673
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2674
  /* Jump here if malloc fails */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2675
whereBeginNoMem:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2676
  whereClauseClear(&wc);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2677
  whereInfoFree(pWInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2678
  return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2679
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2680
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2681
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2682
** Generate the end of the WHERE loop.  See comments on 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2683
** sqlite3WhereBegin() for additional information.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2684
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2685
void sqlite3WhereEnd(WhereInfo *pWInfo){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2686
  Vdbe *v = pWInfo->pParse->pVdbe;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2687
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2688
  WhereLevel *pLevel;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2689
  SrcList *pTabList = pWInfo->pTabList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2690
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2691
  /* Generate loop termination code.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2692
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2693
  for(i=pTabList->nSrc-1; i>=0; i--){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2694
    pLevel = &pWInfo->a[i];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2695
    sqlite3VdbeResolveLabel(v, pLevel->cont);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2696
    if( pLevel->op!=OP_Noop ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2697
      sqlite3VdbeAddOp(v, pLevel->op, pLevel->p1, pLevel->p2);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2698
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2699
    if( pLevel->nIn ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2700
		WhereLevel::InLoop *pIn;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2701
      int j;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2702
      sqlite3VdbeResolveLabel(v, pLevel->nxt);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2703
      for(j=pLevel->nIn, pIn=&pLevel->aInLoop[j-1]; j>0; j--, pIn--){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2704
        sqlite3VdbeJumpHere(v, pIn->topAddr+1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2705
        sqlite3VdbeAddOp(v, OP_Next, pIn->iCur, pIn->topAddr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2706
        sqlite3VdbeJumpHere(v, pIn->topAddr-1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2707
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2708
      sqlite3_free(pLevel->aInLoop);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2709
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2710
    sqlite3VdbeResolveLabel(v, pLevel->brk);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2711
    if( pLevel->iLeftJoin ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2712
      int addr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2713
      addr = sqlite3VdbeAddOp(v, OP_IfMemPos, pLevel->iLeftJoin, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2714
      sqlite3VdbeAddOp(v, OP_NullRow, pTabList->a[i].iCursor, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2715
      if( pLevel->iIdxCur>=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2716
        sqlite3VdbeAddOp(v, OP_NullRow, pLevel->iIdxCur, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2717
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2718
      sqlite3VdbeAddOp(v, OP_Goto, 0, pLevel->top);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2719
      sqlite3VdbeJumpHere(v, addr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2720
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2721
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2722
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2723
  /* The "break" point is here, just past the end of the outer loop.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2724
  ** Set it.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2725
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2726
  sqlite3VdbeResolveLabel(v, pWInfo->iBreak);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2727
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2728
  /* Close all of the cursors that were opened by sqlite3WhereBegin.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2729
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2730
  for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2731
	  SrcList::SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2732
    Table *pTab = pTabItem->pTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2733
    assert( pTab!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2734
    if( pTab->isEphem || pTab->pSelect ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2735
    if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2736
      sqlite3VdbeAddOp(v, OP_Close, pTabItem->iCursor, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2737
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2738
    if( pLevel->pIdx!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2739
      sqlite3VdbeAddOp(v, OP_Close, pLevel->iIdxCur, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2740
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2741
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2742
    /* If this scan uses an index, make code substitutions to read data
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2743
    ** from the index in preference to the table. Sometimes, this means
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2744
    ** the table need never be read from. This is a performance boost,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2745
    ** as the vdbe level waits until the table is read before actually
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2746
    ** seeking the table cursor to the record corresponding to the current
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2747
    ** position in the index.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2748
    ** 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2749
    ** Calls to the code generator in between sqlite3WhereBegin and
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2750
    ** sqlite3WhereEnd will have created code that references the table
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2751
    ** directly.  This loop scans all that code looking for opcodes
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2752
    ** that reference the table and converts them into opcodes that
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2753
    ** reference the index.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2754
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2755
    if( pLevel->pIdx ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2756
      int k, j, last;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2757
      VdbeOp *pOp;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2758
      Index *pIdx = pLevel->pIdx;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2759
      int useIndexOnly = pLevel->flags & WHERE_IDX_ONLY;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2760
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2761
      assert( pIdx!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2762
      pOp = sqlite3VdbeGetOp(v, pWInfo->iTop);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2763
      last = sqlite3VdbeCurrentAddr(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2764
      for(k=pWInfo->iTop; k<last; k++, pOp++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2765
        if( pOp->p1!=pLevel->iTabCur ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2766
        if( pOp->opcode==OP_Column ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2767
          for(j=0; j<pIdx->nColumn; j++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2768
            if( pOp->p2==pIdx->aiColumn[j] ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2769
              pOp->p2 = j;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2770
              pOp->p1 = pLevel->iIdxCur;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2771
              break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2772
            }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2773
          }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2774
          assert(!useIndexOnly || j<pIdx->nColumn);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2775
        }else if( pOp->opcode==OP_Rowid ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2776
          pOp->p1 = pLevel->iIdxCur;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2777
          pOp->opcode = OP_IdxRowid;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2778
        }else if( pOp->opcode==OP_NullRow && useIndexOnly ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2779
          pOp->opcode = OP_Noop;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2780
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2781
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2782
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2783
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2784
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2785
  /* Final cleanup
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2786
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2787
  whereInfoFree(pWInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2788
  return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2789
}