engine/sqlite/src/where.cpp
author Lars Persson <lars.persson@embeddev.se>
Wed, 31 Mar 2010 18:09:02 +0200
changeset 64 b52f6033af15
parent 2 29cda98b007e
permissions -rw-r--r--
Add so image conversion is done in feedinfo if image already exist. Check in feedengine if image exist from previous database(files might exist, even though the db is corrupt.
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
}